meepo 1.5.2
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/.coveralls.yml +1 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +10 -0
- data/Dockerfile +7 -0
- data/Gemfile +13 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +15 -0
- data/TODO +5 -0
- data/bin/invoker +7 -0
- data/contrib/completion/invoker-completion.bash +70 -0
- data/contrib/completion/invoker-completion.zsh +62 -0
- data/examples/hello_sinatra.rb +26 -0
- data/examples/sample.ini +3 -0
- data/invoker.gemspec +43 -0
- data/lib/invoker.rb +152 -0
- data/lib/invoker/cli.rb +159 -0
- data/lib/invoker/cli/pinger.rb +23 -0
- data/lib/invoker/cli/question.rb +15 -0
- data/lib/invoker/cli/tail.rb +34 -0
- data/lib/invoker/cli/tail_watcher.rb +34 -0
- data/lib/invoker/command_worker.rb +60 -0
- data/lib/invoker/commander.rb +95 -0
- data/lib/invoker/daemon.rb +126 -0
- data/lib/invoker/dns_cache.rb +23 -0
- data/lib/invoker/errors.rb +17 -0
- data/lib/invoker/event/manager.rb +79 -0
- data/lib/invoker/ipc.rb +45 -0
- data/lib/invoker/ipc/add_command.rb +12 -0
- data/lib/invoker/ipc/add_http_command.rb +10 -0
- data/lib/invoker/ipc/base_command.rb +24 -0
- data/lib/invoker/ipc/client_handler.rb +26 -0
- data/lib/invoker/ipc/dns_check_command.rb +17 -0
- data/lib/invoker/ipc/list_command.rb +11 -0
- data/lib/invoker/ipc/message.rb +170 -0
- data/lib/invoker/ipc/message/list_response.rb +35 -0
- data/lib/invoker/ipc/message/tail_response.rb +10 -0
- data/lib/invoker/ipc/ping_command.rb +10 -0
- data/lib/invoker/ipc/reload_command.rb +12 -0
- data/lib/invoker/ipc/remove_command.rb +12 -0
- data/lib/invoker/ipc/server.rb +26 -0
- data/lib/invoker/ipc/tail_command.rb +11 -0
- data/lib/invoker/ipc/unix_client.rb +60 -0
- data/lib/invoker/logger.rb +13 -0
- data/lib/invoker/parsers/config.rb +184 -0
- data/lib/invoker/parsers/procfile.rb +86 -0
- data/lib/invoker/power/balancer.rb +131 -0
- data/lib/invoker/power/config.rb +77 -0
- data/lib/invoker/power/dns.rb +38 -0
- data/lib/invoker/power/http_parser.rb +68 -0
- data/lib/invoker/power/http_response.rb +81 -0
- data/lib/invoker/power/pf_migrate.rb +64 -0
- data/lib/invoker/power/port_finder.rb +49 -0
- data/lib/invoker/power/power.rb +3 -0
- data/lib/invoker/power/powerup.rb +29 -0
- data/lib/invoker/power/setup.rb +90 -0
- data/lib/invoker/power/setup/distro/arch.rb +15 -0
- data/lib/invoker/power/setup/distro/base.rb +57 -0
- data/lib/invoker/power/setup/distro/debian.rb +11 -0
- data/lib/invoker/power/setup/distro/mint.rb +10 -0
- data/lib/invoker/power/setup/distro/opensuse.rb +11 -0
- data/lib/invoker/power/setup/distro/redhat.rb +11 -0
- data/lib/invoker/power/setup/distro/ubuntu.rb +10 -0
- data/lib/invoker/power/setup/files/invoker_forwarder.sh.erb +17 -0
- data/lib/invoker/power/setup/files/socat_invoker.service +12 -0
- data/lib/invoker/power/setup/linux_setup.rb +105 -0
- data/lib/invoker/power/setup/osx_setup.rb +137 -0
- data/lib/invoker/power/templates/400.html +40 -0
- data/lib/invoker/power/templates/404.html +40 -0
- data/lib/invoker/power/templates/503.html +40 -0
- data/lib/invoker/power/url_rewriter.rb +40 -0
- data/lib/invoker/process_manager.rb +198 -0
- data/lib/invoker/process_printer.rb +43 -0
- data/lib/invoker/reactor.rb +37 -0
- data/lib/invoker/reactor/reader.rb +54 -0
- data/lib/invoker/version.rb +47 -0
- data/readme.md +25 -0
- data/spec/invoker/cli/pinger_spec.rb +22 -0
- data/spec/invoker/cli/tail_watcher_spec.rb +39 -0
- data/spec/invoker/cli_spec.rb +27 -0
- data/spec/invoker/command_worker_spec.rb +45 -0
- data/spec/invoker/commander_spec.rb +152 -0
- data/spec/invoker/config_spec.rb +361 -0
- data/spec/invoker/daemon_spec.rb +34 -0
- data/spec/invoker/event/manager_spec.rb +67 -0
- data/spec/invoker/invoker_spec.rb +71 -0
- data/spec/invoker/ipc/client_handler_spec.rb +54 -0
- data/spec/invoker/ipc/dns_check_command_spec.rb +32 -0
- data/spec/invoker/ipc/message/list_response_spec.rb +24 -0
- data/spec/invoker/ipc/message_spec.rb +49 -0
- data/spec/invoker/ipc/unix_client_spec.rb +29 -0
- data/spec/invoker/power/balancer_spec.rb +22 -0
- data/spec/invoker/power/config_spec.rb +18 -0
- data/spec/invoker/power/http_parser_spec.rb +32 -0
- data/spec/invoker/power/http_response_spec.rb +34 -0
- data/spec/invoker/power/pf_migrate_spec.rb +87 -0
- data/spec/invoker/power/port_finder_spec.rb +16 -0
- data/spec/invoker/power/setup/linux_setup_spec.rb +103 -0
- data/spec/invoker/power/setup/osx_setup_spec.rb +105 -0
- data/spec/invoker/power/setup_spec.rb +4 -0
- data/spec/invoker/power/url_rewriter_spec.rb +70 -0
- data/spec/invoker/power/web_sockets_spec.rb +61 -0
- data/spec/invoker/process_manager_spec.rb +130 -0
- data/spec/invoker/reactor_spec.rb +6 -0
- data/spec/spec_helper.rb +43 -0
- metadata +389 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Invoker
|
|
2
|
+
class ProcessPrinter
|
|
3
|
+
MAX_COLUMN_WIDTH = 40
|
|
4
|
+
attr_accessor :list_response
|
|
5
|
+
|
|
6
|
+
def initialize(list_response)
|
|
7
|
+
self.list_response = list_response
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def print_table
|
|
11
|
+
hash_with_colors = []
|
|
12
|
+
list_response.processes.each do |process|
|
|
13
|
+
if process.pid
|
|
14
|
+
hash_with_colors << colorize_hash(process, "green")
|
|
15
|
+
else
|
|
16
|
+
hash_with_colors << colorize_hash(process, "light_black")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
Formatador.display_compact_table(hash_with_colors)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def colorize_hash(process, color)
|
|
25
|
+
hash_with_colors = {}
|
|
26
|
+
|
|
27
|
+
hash_with_colors['dir'] = colored_string(process.dir, color)
|
|
28
|
+
hash_with_colors['pid'] = colored_string(process.pid || 'Not Running', color)
|
|
29
|
+
hash_with_colors['port'] = colored_string(process.port, color)
|
|
30
|
+
hash_with_colors['shell_command'] = colored_string(process.shell_command, color)
|
|
31
|
+
hash_with_colors['process_name'] = colored_string(process.process_name, color)
|
|
32
|
+
hash_with_colors
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def colored_string(string, color)
|
|
36
|
+
string = string.to_s
|
|
37
|
+
if string.length > MAX_COLUMN_WIDTH
|
|
38
|
+
string = "#{string[0..MAX_COLUMN_WIDTH]}.."
|
|
39
|
+
end
|
|
40
|
+
"[#{color}]#{string}[/]"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Invoker
|
|
2
|
+
class Reactor
|
|
3
|
+
attr_accessor :reader
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@reader = Invoker::Reactor::Reader.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def watch_for_read(fd)
|
|
10
|
+
reader.watch_for_read(fd)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Writes data to client socket and raises error if errors
|
|
14
|
+
# while writing
|
|
15
|
+
def send_data(socket, data)
|
|
16
|
+
socket.write(data)
|
|
17
|
+
rescue
|
|
18
|
+
raise Invoker::Errors::ClientDisconnected
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def monitor_for_fd_events
|
|
22
|
+
ready_read_fds, _ , _ = select(*options_for_select)
|
|
23
|
+
|
|
24
|
+
if ready_read_fds && !ready_read_fds.empty?
|
|
25
|
+
reader.handle_read_event(ready_read_fds)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def options_for_select
|
|
32
|
+
[reader.read_array, [], [], 0.05]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
require "invoker/reactor/reader"
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Invoker
|
|
2
|
+
class Reactor::Reader
|
|
3
|
+
attr_accessor :read_array
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@read_array = []
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def watch_for_read(socket)
|
|
10
|
+
@read_array << socket
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def handle_read_event(read_ready_fds)
|
|
14
|
+
ready_fds = read_ready_fds.flatten.compact
|
|
15
|
+
ready_fds.each { |ready_fd| process_read(ready_fd) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def process_read(ready_fd)
|
|
21
|
+
command_worker = Invoker.commander.get_worker_from_fd(ready_fd)
|
|
22
|
+
return unless command_worker
|
|
23
|
+
begin
|
|
24
|
+
data = read_data(ready_fd)
|
|
25
|
+
command_worker.receive_data(data)
|
|
26
|
+
rescue Invoker::Errors::ProcessTerminated
|
|
27
|
+
remove_from_read_monitoring(command_worker.pipe_end, command_worker)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def remove_from_read_monitoring(fd, command_worker)
|
|
32
|
+
read_array.delete(fd)
|
|
33
|
+
command_worker.unbind
|
|
34
|
+
rescue StandardError => error
|
|
35
|
+
Invoker::Logger.puts(error.message)
|
|
36
|
+
Invoker::Logger.puts(error.backtrace)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def read_data(ready_fd)
|
|
40
|
+
sock_data = []
|
|
41
|
+
begin
|
|
42
|
+
while(t_data = ready_fd.read_nonblock(64))
|
|
43
|
+
sock_data << t_data
|
|
44
|
+
end
|
|
45
|
+
rescue Errno::EAGAIN
|
|
46
|
+
return sock_data.join
|
|
47
|
+
rescue Errno::EWOULDBLOCK
|
|
48
|
+
return sock_data.join
|
|
49
|
+
rescue
|
|
50
|
+
raise Invoker::Errors::ProcessTerminated.new(ready_fd,sock_data.join)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Invoker
|
|
2
|
+
class Version
|
|
3
|
+
include Comparable
|
|
4
|
+
attr_reader :major, :minor, :patch
|
|
5
|
+
|
|
6
|
+
def initialize(number)
|
|
7
|
+
t_major, t_minor, t_patch = number.split('.')
|
|
8
|
+
@major = t_major.to_i
|
|
9
|
+
@minor = t_minor.to_i
|
|
10
|
+
@patch = t_patch.to_i
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_a
|
|
14
|
+
[major, minor, patch].compact
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def <=>(version)
|
|
18
|
+
(major.to_i <=> version.major.to_i).nonzero? ||
|
|
19
|
+
(minor.to_i <=> version.minor.to_i).nonzero? ||
|
|
20
|
+
patch.to_i <=> version.patch.to_i
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def matches?(operator, number)
|
|
24
|
+
version = Version.new(number)
|
|
25
|
+
self == version
|
|
26
|
+
|
|
27
|
+
return self == version if operator == '='
|
|
28
|
+
return self > version if operator == '>'
|
|
29
|
+
return self < version if operator == '<'
|
|
30
|
+
return version <= self && version.next > self if operator == '~>'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def next
|
|
34
|
+
next_splits = to_a
|
|
35
|
+
|
|
36
|
+
if next_splits.length == 1
|
|
37
|
+
next_splits[0] += 1
|
|
38
|
+
else
|
|
39
|
+
next_splits[-2] += 1
|
|
40
|
+
next_splits[-1] = 0
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Version.new(next_splits.join('.'))
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
VERSION = "1.5.2"
|
|
47
|
+
end
|
data/readme.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Invoker is a gem for managing processes in development environment.
|
|
2
|
+
|
|
3
|
+
[](https://travis-ci.org/code-mancers/invoker)
|
|
4
|
+
[](https://codeclimate.com/github/code-mancers/invoker)
|
|
5
|
+
[](https://coveralls.io/r/code-mancers/invoker)
|
|
6
|
+
[](https://gemnasium.com/code-mancers/invoker)
|
|
7
|
+
|
|
8
|
+
## Usage ##
|
|
9
|
+
|
|
10
|
+
First we need to install `invoker` gem to get command line utility called `invoker`, we can do that via:
|
|
11
|
+
|
|
12
|
+
gem install invoker
|
|
13
|
+
|
|
14
|
+
Currently it only works with Ruby 1.9.3, 2.0 and 2.1.
|
|
15
|
+
|
|
16
|
+
## Manual ##
|
|
17
|
+
|
|
18
|
+
Information about configuring and using Invoker can be found on - [Invoker Website](http://invoker.codemancers.com)
|
|
19
|
+
|
|
20
|
+
Invoker documentation is maintained via `Jekyll` and hosted on `github`. If you would like to fix an error
|
|
21
|
+
or update something - please submit a pull request against `gh-pages` branch of `Invoker`.
|
|
22
|
+
|
|
23
|
+
## Bug reports and Feature requests
|
|
24
|
+
|
|
25
|
+
Please use [Github Issue Tracker](https://github.com/code-mancers/invoker/issues) for feature requests or bug reports.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Invoker::CLI::Pinger do
|
|
4
|
+
let(:unix_client) { Invoker::IPC::UnixClient.new }
|
|
5
|
+
let(:pinger) { Invoker::CLI::Pinger.new(unix_client) }
|
|
6
|
+
let(:pong) { MM::Pong.new(status: 'pong') }
|
|
7
|
+
|
|
8
|
+
context "If Invoker is running" do
|
|
9
|
+
it "should return true" do
|
|
10
|
+
unix_client.expects(:send_and_receive).returns(pong)
|
|
11
|
+
expect(pinger.invoker_running?).to be_truthy
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context "if Invoker is not running" do
|
|
16
|
+
it "should return false" do
|
|
17
|
+
unix_client.expects(:send_and_receive).returns(nil)
|
|
18
|
+
unix_client.expects(:abort).never
|
|
19
|
+
expect(pinger.invoker_running?).to be_falsey
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Invoker::CLI::TailWatcher do
|
|
4
|
+
let(:tail_watcher) { Invoker::CLI::TailWatcher.new }
|
|
5
|
+
|
|
6
|
+
describe "Adding processes to watch list" do
|
|
7
|
+
it "should allow add" do
|
|
8
|
+
tail_watcher.add(["rails"], "socket")
|
|
9
|
+
expect(tail_watcher.tail_watchers).to_not be_empty
|
|
10
|
+
expect(tail_watcher["rails"]).to eql ["socket"]
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "removing processes from watch list" do
|
|
15
|
+
context "when process has only one watcher" do
|
|
16
|
+
before do
|
|
17
|
+
tail_watcher.add(["rails"], "socket")
|
|
18
|
+
end
|
|
19
|
+
it "should remove and purge process watch list" do
|
|
20
|
+
expect(tail_watcher.tail_watchers).to_not be_empty
|
|
21
|
+
tail_watcher.remove("rails", "socket")
|
|
22
|
+
expect(tail_watcher.tail_watchers).to be_empty
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
context "when process multiple watchers" do
|
|
26
|
+
before do
|
|
27
|
+
tail_watcher.add(["rails"], "socket")
|
|
28
|
+
tail_watcher.add(["rails"], "socket2")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should remove only related socket" do
|
|
32
|
+
expect(tail_watcher.tail_watchers).to_not be_empty
|
|
33
|
+
tail_watcher.remove("rails", "socket")
|
|
34
|
+
expect(tail_watcher.tail_watchers).to_not be_empty
|
|
35
|
+
expect(tail_watcher["rails"]).to eql ["socket2"]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Invoker::CLI do
|
|
4
|
+
describe "default start command" do
|
|
5
|
+
it "should use default if no other command specified" do
|
|
6
|
+
Invoker::CLI.any_instance.expects(:start).with("dummy")
|
|
7
|
+
Invoker::CLI.start(["dummy"])
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should use proper command if it exists" do
|
|
11
|
+
Invoker::CLI.any_instance.expects(:list)
|
|
12
|
+
Invoker::CLI.start(["list"])
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should list version" do
|
|
16
|
+
Invoker::CLI.any_instance.expects(:version)
|
|
17
|
+
Invoker::CLI.start(["-v"])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe "stop command" do
|
|
22
|
+
it "should stop the daemon" do
|
|
23
|
+
Invoker.daemon.expects(:stop).once
|
|
24
|
+
Invoker::CLI.start(["stop"])
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe "Command Worker" do
|
|
4
|
+
let(:pipe_end) { StringIO.new }
|
|
5
|
+
let(:command_worker) { Invoker::CommandWorker.new('rails', pipe_end, 100, :red) }
|
|
6
|
+
|
|
7
|
+
describe "converting workers hash to json" do
|
|
8
|
+
before do
|
|
9
|
+
@workers = {}
|
|
10
|
+
@workers["foo"] = Invoker::CommandWorker.new("foo", 89, 1023, "red")
|
|
11
|
+
@workers["bar"] = Invoker::CommandWorker.new("bar", 99, 1024, "blue")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should print json" do
|
|
15
|
+
expect(@workers.values.map {|worker| worker.to_h }.to_json).not_to be_empty
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "sending json responses" do
|
|
20
|
+
before do
|
|
21
|
+
@socket = StringIO.new
|
|
22
|
+
Invoker.tail_watchers = Invoker::CLI::TailWatcher.new
|
|
23
|
+
Invoker.tail_watchers.add(['rails'], @socket)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
after do
|
|
27
|
+
Invoker.tail_watchers = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context "when there is a error encoding the message" do
|
|
31
|
+
it "should send nothing to the socket" do
|
|
32
|
+
MM::TailResponse.any_instance.expects(:encoded_message).raises(StandardError, "encoding error")
|
|
33
|
+
command_worker.receive_line('hello_world')
|
|
34
|
+
expect(@socket.string).to be_empty
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "when there is successful delivery" do
|
|
39
|
+
it "should return json data to client if tail watchers" do
|
|
40
|
+
command_worker.receive_line('hello_world')
|
|
41
|
+
expect(@socket.string).to match(/hello_world/)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe "Invoker::Commander" do
|
|
4
|
+
before(:each) do
|
|
5
|
+
@original_invoker_config = Invoker.config
|
|
6
|
+
Invoker.config = mock
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
after(:each) do
|
|
10
|
+
Invoker.config = @original_invoker_config
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "With no processes configured" do
|
|
14
|
+
before(:each) do
|
|
15
|
+
@commander = Invoker::Commander.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should throw error" do
|
|
19
|
+
Invoker.config.stubs(:processes).returns([])
|
|
20
|
+
|
|
21
|
+
expect {
|
|
22
|
+
@commander.start_manager
|
|
23
|
+
}.to raise_error(Invoker::Errors::InvalidConfig)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "#start_process" do
|
|
28
|
+
describe "when not daemonized" do
|
|
29
|
+
before do
|
|
30
|
+
processes = [OpenStruct.new(:label => "foobar", :cmd => "foobar_command", :dir => ENV['HOME'], :sleep_duration => 2)]
|
|
31
|
+
Invoker.config.stubs(:processes).returns(processes)
|
|
32
|
+
Invoker.config.stubs(:autorunnable_processes).returns(processes)
|
|
33
|
+
Invoker.stubs(:can_run_balancer?).returns(false)
|
|
34
|
+
@commander = Invoker::Commander.new
|
|
35
|
+
Invoker.commander = @commander
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
after do
|
|
39
|
+
Invoker.commander = nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should populate workers and open_pipes" do
|
|
43
|
+
@commander.expects(:start_event_loop)
|
|
44
|
+
@commander.process_manager.expects(:load_env).returns({})
|
|
45
|
+
@commander.process_manager.expects(:spawn).returns(100)
|
|
46
|
+
@commander.process_manager.expects(:wait_on_pid)
|
|
47
|
+
@commander.expects(:at_exit)
|
|
48
|
+
@commander.start_manager
|
|
49
|
+
expect(@commander.process_manager.open_pipes).not_to be_empty
|
|
50
|
+
expect(@commander.process_manager.workers).not_to be_empty
|
|
51
|
+
|
|
52
|
+
worker = @commander.process_manager.workers['foobar']
|
|
53
|
+
|
|
54
|
+
expect(worker).not_to be_nil
|
|
55
|
+
expect(worker.command_label).to eq('foobar')
|
|
56
|
+
|
|
57
|
+
pipe_end_worker = @commander.process_manager.open_pipes[worker.pipe_end.fileno]
|
|
58
|
+
expect(pipe_end_worker).not_to be_nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "when daemonized" do
|
|
63
|
+
before do
|
|
64
|
+
processes = [OpenStruct.new(:label => "foobar", :cmd => "foobar_command", :dir => ENV['HOME'], :sleep_duration => 2)]
|
|
65
|
+
Invoker.config.stubs(:processes).returns(processes)
|
|
66
|
+
Invoker.config.stubs(:autorunnable_processes).returns(processes)
|
|
67
|
+
Invoker.stubs(:can_run_balancer?).returns(false)
|
|
68
|
+
@commander = Invoker::Commander.new
|
|
69
|
+
Invoker.commander = @commander
|
|
70
|
+
Invoker.daemonize = true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
after do
|
|
74
|
+
Invoker.commander = nil
|
|
75
|
+
Invoker.daemonize = false
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should daemonize the process and populate workers and open_pipes" do
|
|
79
|
+
@commander.expects(:start_event_loop)
|
|
80
|
+
@commander.process_manager.expects(:load_env).returns({})
|
|
81
|
+
Invoker.daemon.expects(:start).once
|
|
82
|
+
@commander.process_manager.expects(:spawn).returns(100)
|
|
83
|
+
@commander.process_manager.expects(:wait_on_pid)
|
|
84
|
+
@commander.expects(:at_exit)
|
|
85
|
+
@commander.start_manager
|
|
86
|
+
|
|
87
|
+
expect(@commander.process_manager.open_pipes).not_to be_empty
|
|
88
|
+
expect(@commander.process_manager.workers).not_to be_empty
|
|
89
|
+
|
|
90
|
+
worker = @commander.process_manager.workers['foobar']
|
|
91
|
+
|
|
92
|
+
expect(worker).not_to be_nil
|
|
93
|
+
expect(worker.command_label).to eq('foobar')
|
|
94
|
+
|
|
95
|
+
pipe_end_worker = @commander.process_manager.open_pipes[worker.pipe_end.fileno]
|
|
96
|
+
expect(pipe_end_worker).not_to be_nil
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe 'disable_autorun option' do
|
|
102
|
+
context 'autorun is disabled for a process' do
|
|
103
|
+
before do
|
|
104
|
+
@processes = [
|
|
105
|
+
OpenStruct.new(:label => "foobar", :cmd => "foobar_command", :dir => ENV['HOME'], :sleep_duration => 2),
|
|
106
|
+
OpenStruct.new(:label => "panda", :cmd => "panda_command", :dir => ENV['HOME'], :disable_autorun => true, :sleep_duration => 2)
|
|
107
|
+
]
|
|
108
|
+
Invoker.config.stubs(:processes).returns(@processes)
|
|
109
|
+
Invoker.config.stubs(:autorunnable_processes).returns([@processes.first])
|
|
110
|
+
|
|
111
|
+
@commander = Invoker::Commander.new
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "doesn't run process" do
|
|
115
|
+
@commander.expects(:install_interrupt_handler)
|
|
116
|
+
@commander.process_manager.expects(:run_power_server)
|
|
117
|
+
@commander.expects(:at_exit)
|
|
118
|
+
@commander.expects(:start_event_loop)
|
|
119
|
+
|
|
120
|
+
@commander.process_manager.expects(:start_process).with(@processes[0])
|
|
121
|
+
@commander.process_manager.expects(:start_process).with(@processes[1]).never
|
|
122
|
+
@commander.start_manager
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
describe "#runnables" do
|
|
128
|
+
before do
|
|
129
|
+
@commander = Invoker::Commander.new
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "should run runnables in reactor tick with one argument" do
|
|
133
|
+
@commander.on_next_tick("foo") { |cmd| start_process_by_name(cmd) }
|
|
134
|
+
@commander.expects(:start_process_by_name).returns(true)
|
|
135
|
+
@commander.run_runnables()
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "should run runnables with multiple args" do
|
|
139
|
+
@commander.on_next_tick("foo", "bar", "baz") { |t1,*rest|
|
|
140
|
+
stop_process(t1, rest)
|
|
141
|
+
}
|
|
142
|
+
@commander.expects(:stop_process).with("foo", ["bar", "baz"]).returns(true)
|
|
143
|
+
@commander.run_runnables()
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should run runnable with no args" do
|
|
147
|
+
@commander.on_next_tick() { hello() }
|
|
148
|
+
@commander.expects(:hello).returns(true)
|
|
149
|
+
@commander.run_runnables()
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|