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 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
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - 2.1.0
8
+ - jruby
9
+ notifications:
10
+ irc:
11
+ - "irc.freenode.net#sensu"
12
+ addons:
13
+ code_climate:
14
+ repo_token: 6e0d725a7d86b1565bc5a8cfa218cf9fb59811b8d4b030e62b6a4745da9f0f96
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sensu-spawn.gemspec
4
+ gemspec
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
+ [![Build Status](https://travis-ci.org/sensu/sensu-spawn.svg?branch=master)](https://travis-ci.org/sensu/sensu-spawn)
4
+
5
+ [![Code Climate](https://codeclimate.com/github/sensu/sensu-spawn.png)](https://codeclimate.com/github/sensu/sensu-spawn)
6
+ [![Code Climate Coverage](https://codeclimate.com/github/sensu/sensu-spawn/coverage.png)](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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -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
@@ -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
@@ -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