sensu-spawn 0.0.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 +7 -0
- data/.gitignore +22 -0
- data/.travis.yml +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +20 -0
- data/README.md +18 -0
- data/Rakefile +6 -0
- data/lib/sensu/spawn.rb +101 -0
- data/sensu-spawn.gemspec +26 -0
- data/spec/helpers.rb +29 -0
- data/spec/spawn_spec.rb +56 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ba8734244c981a6acf5d366a6e0ee890251c7b9b
|
4
|
+
data.tar.gz: de35257b0ebca2fe72e009ed76ce3ce8cf6f85f3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6a1012cfe26fc965aa1f722d108f71ccbd93edf358c83aac5d18b93f0ad4f511c837e8a6b1728db70456da20bf20f5bf8fd604e08bfaf7ddc3154dd9459d8e3a
|
7
|
+
data.tar.gz: 5d714f4e75834070d2642645a24d8bc0de11688356e312a499b5b45d7eeff56c9f4cb3ce79b9141f99783daa419e2f0d046348b3f85a0218387378cc0a98c541
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2014 Heavy Water Operations, LLC.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Sensu::Spawn
|
2
|
+
|
3
|
+
[](https://travis-ci.org/sensu/sensu-spawn)
|
4
|
+
|
5
|
+
[](https://codeclimate.com/github/sensu/sensu-spawn)
|
6
|
+
[](https://codeclimate.com/github/sensu/sensu-spawn)
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
Documentation can be found [here](http://rubydoc.info/github/sensu/sensu-spawn/Sensu/Spawn).
|
11
|
+
|
12
|
+
## Contributing
|
13
|
+
|
14
|
+
1. [Fork it](https://github.com/sensu/sensu-spawn/fork)
|
15
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
16
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
17
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
18
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/lib/sensu/spawn.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
gem "sensu-em"
|
2
|
+
gem "em-worker", "0.0.2"
|
3
|
+
gem "childprocess", "0.5.3"
|
4
|
+
|
5
|
+
require "eventmachine"
|
6
|
+
require "em/worker"
|
7
|
+
require "childprocess"
|
8
|
+
|
9
|
+
module Sensu
|
10
|
+
module Spawn
|
11
|
+
class << self
|
12
|
+
# Spawn a child process. A maximum of 12 processes will be
|
13
|
+
# spawned at a time. The EventMachine reactor (loop) must be
|
14
|
+
# running for this method to work.
|
15
|
+
#
|
16
|
+
# @param [String] command to run.
|
17
|
+
# @param [Hash] options to create a child process with.
|
18
|
+
# @option options [String] :data to write to STDIN.
|
19
|
+
# @option options [Integer] :timeout in seconds.
|
20
|
+
# @param [Proc] callback called when the child process exits,
|
21
|
+
# its output and exit status are passed as parameters.
|
22
|
+
def process(command, options={}, &callback)
|
23
|
+
create = Proc.new do
|
24
|
+
child_process(command, options)
|
25
|
+
end
|
26
|
+
@process_worker ||= EM::Worker.new(:concurrency => 12)
|
27
|
+
@process_worker.enqueue(create, callback)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Build a child process attached to a pipe, in order to capture
|
31
|
+
# its output (STDERR, STDOUT). The child process will be a
|
32
|
+
# platform dependent shell, that is responsible for executing
|
33
|
+
# the provided command.
|
34
|
+
#
|
35
|
+
# @param [String] command to run.
|
36
|
+
# @return [Array] child object, pipe reader, pipe writer.
|
37
|
+
def build_child_process(command)
|
38
|
+
reader, writer = IO.pipe
|
39
|
+
shell = case RUBY_PLATFORM
|
40
|
+
when /(ms|cyg|bcc)win|mingw|win32/
|
41
|
+
["cmd", "/c"]
|
42
|
+
else
|
43
|
+
["sh", "-c"]
|
44
|
+
end
|
45
|
+
ChildProcess.posix_spawn = true
|
46
|
+
shell_command = shell + [command]
|
47
|
+
child = ChildProcess.build(*shell_command)
|
48
|
+
child.io.stdout = child.io.stderr = writer
|
49
|
+
child.leader = true
|
50
|
+
[child, reader, writer]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Read a stream/file until end of file (EOF).
|
54
|
+
#
|
55
|
+
# @param [Object] reader to read contents of until EOF.
|
56
|
+
# @return [String] the stream/file contents.
|
57
|
+
def read_until_eof(reader)
|
58
|
+
output = ""
|
59
|
+
begin
|
60
|
+
loop { output << reader.readpartial(8192) }
|
61
|
+
rescue EOFError
|
62
|
+
end
|
63
|
+
reader.close
|
64
|
+
output
|
65
|
+
end
|
66
|
+
|
67
|
+
# Create a child process, return its output (STDERR & STDOUT),
|
68
|
+
# and exit status. The child process will have its own process
|
69
|
+
# group, may accept data via STDIN, and have a timeout.
|
70
|
+
#
|
71
|
+
# @param [String] command to run.
|
72
|
+
# @param [Hash] options to create a child process with.
|
73
|
+
# @option options [String] :data to write to STDIN.
|
74
|
+
# @option options [Integer] :timeout in seconds.
|
75
|
+
# @return [Array] child process output and exit status.
|
76
|
+
def child_process(command, options={})
|
77
|
+
child, reader, writer = build_child_process(command)
|
78
|
+
child.duplex = true if options[:data]
|
79
|
+
child.start
|
80
|
+
if options[:data]
|
81
|
+
child.io.stdin.write(options[:data])
|
82
|
+
child.io.stdin.close
|
83
|
+
end
|
84
|
+
if options[:timeout]
|
85
|
+
child.poll_for_exit(options[:timeout])
|
86
|
+
else
|
87
|
+
child.wait
|
88
|
+
end
|
89
|
+
writer.close
|
90
|
+
output = read_until_eof(reader)
|
91
|
+
[output, child.exit_code]
|
92
|
+
rescue ChildProcess::TimeoutError
|
93
|
+
child.stop
|
94
|
+
["Execution timed out", 2]
|
95
|
+
rescue => error
|
96
|
+
child.stop
|
97
|
+
["Unexpected error: #{error}", 3]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/sensu-spawn.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "sensu-spawn"
|
5
|
+
spec.version = "0.0.1"
|
6
|
+
spec.authors = ["Sean Porter"]
|
7
|
+
spec.email = ["portertech@gmail.com"]
|
8
|
+
spec.summary = "The Sensu spawn process library"
|
9
|
+
spec.description = "The Sensu spawn process library"
|
10
|
+
spec.homepage = "https://github.com/sensu/sensu-spawn"
|
11
|
+
spec.license = "MIT"
|
12
|
+
|
13
|
+
spec.files = `git ls-files -z`.split("\x0")
|
14
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
15
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
16
|
+
spec.require_paths = ["lib"]
|
17
|
+
|
18
|
+
spec.add_dependency "sensu-em"
|
19
|
+
spec.add_dependency "em-worker", "0.0.2"
|
20
|
+
spec.add_dependency "childprocess", "0.5.3"
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec"
|
25
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
26
|
+
end
|
data/spec/helpers.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "rspec"
|
2
|
+
require "eventmachine"
|
3
|
+
|
4
|
+
unless RUBY_VERSION < "1.9" || RUBY_PLATFORM =~ /java/
|
5
|
+
require "codeclimate-test-reporter"
|
6
|
+
CodeClimate::TestReporter.start
|
7
|
+
end
|
8
|
+
|
9
|
+
module Helpers
|
10
|
+
def timer(delay, &callback)
|
11
|
+
periodic_timer = EM::PeriodicTimer.new(delay) do
|
12
|
+
callback.call
|
13
|
+
periodic_timer.cancel
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def async_wrapper(&callback)
|
18
|
+
EM.run do
|
19
|
+
timer(10) do
|
20
|
+
raise "test timed out"
|
21
|
+
end
|
22
|
+
callback.call
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def async_done
|
27
|
+
EM.stop_event_loop
|
28
|
+
end
|
29
|
+
end
|
data/spec/spawn_spec.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "helpers")
|
2
|
+
require "sensu/spawn"
|
3
|
+
|
4
|
+
describe "Sensu::Spawn" do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
it "can spawn a process" do
|
8
|
+
async_wrapper do
|
9
|
+
Sensu::Spawn.process("echo foo") do |output, status|
|
10
|
+
expect(output).to eq("foo\n")
|
11
|
+
expect(status).to eq(0)
|
12
|
+
async_done
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "can spawn a process with a non-zero exit status" do
|
18
|
+
async_wrapper do
|
19
|
+
Sensu::Spawn.process("echo foo && exit 1") do |output, status|
|
20
|
+
expect(output).to eq("foo\n")
|
21
|
+
expect(status).to eq(1)
|
22
|
+
async_done
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "can spawn a process using an unknown command" do
|
28
|
+
async_wrapper do
|
29
|
+
Sensu::Spawn.process("unknown.command") do |output, status|
|
30
|
+
expect(output).to include("unknown")
|
31
|
+
expect(status).to eq(127)
|
32
|
+
async_done
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can spawn a process with a timeout" do
|
38
|
+
async_wrapper do
|
39
|
+
Sensu::Spawn.process("sleep 5", :timeout => 0.5) do |output, status|
|
40
|
+
expect(output).to eq("Execution timed out")
|
41
|
+
expect(status).to eq(2)
|
42
|
+
async_done
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "can spawn a process that reads from STDIN" do
|
48
|
+
async_wrapper do
|
49
|
+
Sensu::Spawn.process("cat", :data => "bar") do |output, status|
|
50
|
+
expect(output).to eq("bar")
|
51
|
+
expect(status).to eq(0)
|
52
|
+
async_done
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sensu-spawn
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean Porter
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sensu-em
|
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: em-worker
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: childprocess
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.5.3
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.5.3
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.6'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: codeclimate-test-reporter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: The Sensu spawn process library
|
112
|
+
email:
|
113
|
+
- portertech@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".travis.yml"
|
120
|
+
- Gemfile
|
121
|
+
- LICENSE.txt
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- lib/sensu/spawn.rb
|
125
|
+
- sensu-spawn.gemspec
|
126
|
+
- spec/helpers.rb
|
127
|
+
- spec/spawn_spec.rb
|
128
|
+
homepage: https://github.com/sensu/sensu-spawn
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
metadata: {}
|
132
|
+
post_install_message:
|
133
|
+
rdoc_options: []
|
134
|
+
require_paths:
|
135
|
+
- lib
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
requirements: []
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 2.2.0
|
149
|
+
signing_key:
|
150
|
+
specification_version: 4
|
151
|
+
summary: The Sensu spawn process library
|
152
|
+
test_files:
|
153
|
+
- spec/helpers.rb
|
154
|
+
- spec/spawn_spec.rb
|