invoker 1.0.4 → 1.1.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.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/.rubocop.yml +30 -0
- data/.travis.yml +1 -0
- data/Gemfile +1 -0
- data/bin/invoker +4 -8
- data/invoker.gemspec +10 -11
- data/lib/invoker.rb +95 -21
- data/lib/invoker/cli.rb +126 -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 +28 -2
- data/lib/invoker/commander.rb +34 -236
- data/lib/invoker/config.rb +5 -0
- data/lib/invoker/daemon.rb +126 -0
- data/lib/invoker/dns_cache.rb +23 -0
- data/lib/invoker/errors.rb +1 -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 +16 -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 +33 -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/{command_listener → ipc}/server.rb +6 -11
- data/lib/invoker/ipc/tail_command.rb +11 -0
- data/lib/invoker/ipc/unix_client.rb +60 -0
- data/lib/invoker/parsers/config.rb +1 -0
- data/lib/invoker/power/balancer.rb +17 -7
- data/lib/invoker/power/config.rb +6 -3
- data/lib/invoker/power/dns.rb +22 -21
- data/lib/invoker/power/http_response.rb +1 -1
- data/lib/invoker/power/power.rb +3 -0
- data/lib/invoker/power/powerup.rb +3 -2
- data/lib/invoker/power/setup.rb +6 -4
- data/lib/invoker/process_manager.rb +187 -0
- data/lib/invoker/process_printer.rb +27 -38
- data/lib/invoker/reactor.rb +19 -38
- data/lib/invoker/reactor/reader.rb +53 -0
- data/lib/invoker/version.rb +1 -1
- data/readme.md +1 -1
- 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 +30 -0
- data/spec/invoker/commander_spec.rb +57 -127
- data/spec/invoker/config_spec.rb +21 -0
- data/spec/invoker/daemon_spec.rb +34 -0
- data/spec/invoker/invoker_spec.rb +31 -0
- data/spec/invoker/ipc/client_handler_spec.rb +44 -0
- data/spec/invoker/ipc/dns_check_command_spec.rb +32 -0
- data/spec/invoker/ipc/message/list_response_spec.rb +22 -0
- data/spec/invoker/ipc/message_spec.rb +45 -0
- data/spec/invoker/ipc/unix_client_spec.rb +29 -0
- data/spec/invoker/power/setup_spec.rb +1 -1
- data/spec/invoker/process_manager_spec.rb +98 -0
- data/spec/invoker/reactor_spec.rb +6 -0
- data/spec/spec_helper.rb +15 -24
- metadata +107 -77
- data/lib/invoker/command_listener/client.rb +0 -45
- data/lib/invoker/parsers/option_parser.rb +0 -106
- data/lib/invoker/power.rb +0 -7
- data/lib/invoker/runner.rb +0 -98
- data/spec/invoker/command_listener/client_spec.rb +0 -52
@@ -1,53 +1,42 @@
|
|
1
1
|
module Invoker
|
2
2
|
class ProcessPrinter
|
3
3
|
MAX_COLUMN_WIDTH = 40
|
4
|
-
|
5
|
-
final_json = []
|
6
|
-
Invoker::CONFIG.processes.each do |process|
|
7
|
-
if worker = workers[process.label]
|
8
|
-
final_json << {
|
9
|
-
:command => process.cmd, :command_label => process.label,
|
10
|
-
:dir => process.dir, :pid => worker.pid
|
11
|
-
}
|
12
|
-
else
|
13
|
-
final_json << {
|
14
|
-
:command => process.cmd, :command_label => process.label,
|
15
|
-
:dir => process.dir
|
16
|
-
}
|
17
|
-
end
|
18
|
-
end
|
4
|
+
attr_accessor :list_response
|
19
5
|
|
20
|
-
|
6
|
+
def initialize(list_response)
|
7
|
+
self.list_response = list_response
|
21
8
|
end
|
22
9
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
else
|
31
|
-
json_row["pid"] = "[light_black]not running[/]"
|
32
|
-
json_for_printing << colorize_hash(json_row, "light_black")
|
33
|
-
end
|
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")
|
34
17
|
end
|
35
|
-
Formatador.display_compact_table(json_for_printing)
|
36
18
|
end
|
19
|
+
Formatador.display_compact_table(hash_with_colors)
|
37
20
|
end
|
38
21
|
|
39
22
|
private
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
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['shell_command'] = colored_string(process.shell_command, color)
|
30
|
+
hash_with_colors['process_name'] = colored_string(process.process_name, color)
|
31
|
+
hash_with_colors
|
50
32
|
end
|
51
33
|
|
34
|
+
def colored_string(string, color)
|
35
|
+
string = string.to_s
|
36
|
+
if string.length > MAX_COLUMN_WIDTH
|
37
|
+
string = "#{string[0..MAX_COLUMN_WIDTH]}.."
|
38
|
+
end
|
39
|
+
"[#{color}]#{string}[/]"
|
40
|
+
end
|
52
41
|
end
|
53
42
|
end
|
data/lib/invoker/reactor.rb
CHANGED
@@ -1,56 +1,37 @@
|
|
1
1
|
module Invoker
|
2
2
|
class Reactor
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :reader
|
4
|
+
|
4
5
|
def initialize
|
5
|
-
@
|
6
|
+
@reader = Invoker::Reactor::Reader.new
|
6
7
|
end
|
7
8
|
|
8
|
-
def
|
9
|
-
|
9
|
+
def watch_for_read(fd)
|
10
|
+
reader.watch_for_read(fd)
|
10
11
|
end
|
11
12
|
|
12
|
-
|
13
|
-
|
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
|
14
19
|
end
|
15
20
|
|
16
|
-
def
|
17
|
-
ready_read_fds,
|
21
|
+
def monitor_for_fd_events
|
22
|
+
ready_read_fds, _ , _ = select(*options_for_select)
|
18
23
|
|
19
24
|
if ready_read_fds && !ready_read_fds.empty?
|
20
|
-
handle_read_event(ready_read_fds)
|
25
|
+
reader.handle_read_event(ready_read_fds)
|
21
26
|
end
|
22
27
|
end
|
23
28
|
|
24
|
-
|
25
|
-
ready_fds = ready_read_fds.flatten.compact
|
26
|
-
ready_fds.each {|ready_fd| process_read(ready_fd) }
|
27
|
-
end
|
28
|
-
|
29
|
-
def process_read(ready_fd)
|
30
|
-
command_worker = Invoker::COMMANDER.get_worker_from_fd(ready_fd)
|
31
|
-
begin
|
32
|
-
data = read_data(ready_fd)
|
33
|
-
command_worker.receive_data(data)
|
34
|
-
rescue Invoker::Errors::ProcessTerminated
|
35
|
-
remove_from_monitoring(command_worker.pipe_end)
|
36
|
-
command_worker.unbind()
|
37
|
-
end
|
38
|
-
end
|
29
|
+
private
|
39
30
|
|
40
|
-
def
|
41
|
-
|
42
|
-
begin
|
43
|
-
while(t_data = ready_fd.read_nonblock(64))
|
44
|
-
sock_data << t_data
|
45
|
-
end
|
46
|
-
rescue Errno::EAGAIN
|
47
|
-
return sock_data.join
|
48
|
-
rescue Errno::EWOULDBLOCK
|
49
|
-
return sock_data.join
|
50
|
-
rescue
|
51
|
-
raise Invoker::Errors::ProcessTerminated.new(ready_fd,sock_data.join)
|
52
|
-
end
|
31
|
+
def options_for_select
|
32
|
+
[reader.read_array, [], [], 0.05]
|
53
33
|
end
|
54
|
-
|
55
34
|
end
|
56
35
|
end
|
36
|
+
|
37
|
+
require "invoker/reactor/reader"
|
@@ -0,0 +1,53 @@
|
|
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
|
+
begin
|
23
|
+
data = read_data(ready_fd)
|
24
|
+
command_worker.receive_data(data)
|
25
|
+
rescue Invoker::Errors::ProcessTerminated
|
26
|
+
remove_from_read_monitoring(command_worker.pipe_end, command_worker)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove_from_read_monitoring(fd, command_worker)
|
31
|
+
read_array.delete(fd)
|
32
|
+
command_worker.unbind
|
33
|
+
rescue StandardError => error
|
34
|
+
Invoker::Logger.puts(error.message)
|
35
|
+
Invoker::Logger.puts(error.backtrace)
|
36
|
+
end
|
37
|
+
|
38
|
+
def read_data(ready_fd)
|
39
|
+
sock_data = []
|
40
|
+
begin
|
41
|
+
while(t_data = ready_fd.read_nonblock(64))
|
42
|
+
sock_data << t_data
|
43
|
+
end
|
44
|
+
rescue Errno::EAGAIN
|
45
|
+
return sock_data.join
|
46
|
+
rescue Errno::EWOULDBLOCK
|
47
|
+
return sock_data.join
|
48
|
+
rescue
|
49
|
+
raise Invoker::Errors::ProcessTerminated.new(ready_fd,sock_data.join)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/invoker/version.rb
CHANGED
data/readme.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Invoker is a gem for managing processes in development environment.
|
2
2
|
|
3
3
|
[](https://travis-ci.org/code-mancers/invoker)
|
4
|
-
[](https://codeclimate.com/github/code-mancers/invoker)
|
5
5
|
[](https://coveralls.io/r/code-mancers/invoker)
|
6
6
|
[](https://gemnasium.com/code-mancers/invoker)
|
7
7
|
|
@@ -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_true
|
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_false
|
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
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe "Command Worker" do
|
4
|
+
let(:pipe_end) { StringIO.new }
|
5
|
+
let(:command_worker) { Invoker::CommandWorker.new('rails', pipe_end, 100, :red) }
|
6
|
+
|
4
7
|
describe "converting workers hash to json" do
|
5
8
|
before do
|
6
9
|
@workers = {}
|
@@ -12,4 +15,31 @@ describe "Command Worker" do
|
|
12
15
|
expect(@workers.values.map {|worker| worker.to_h }.to_json).not_to be_empty
|
13
16
|
end
|
14
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
|
15
45
|
end
|
@@ -1,132 +1,108 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe "Invoker::Commander" do
|
4
|
-
|
5
4
|
describe "With no processes configured" do
|
6
5
|
before do
|
7
|
-
@commander = Invoker::Commander.new
|
6
|
+
@commander = Invoker::Commander.new
|
8
7
|
end
|
9
8
|
|
10
9
|
it "should throw error" do
|
11
10
|
invoker_config.stubs(:processes).returns([])
|
12
11
|
|
13
12
|
expect {
|
14
|
-
@commander.start_manager
|
13
|
+
@commander.start_manager
|
15
14
|
}.to raise_error(Invoker::Errors::InvalidConfig)
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
19
|
-
describe "#
|
20
|
-
|
21
|
-
@commander = Invoker::Commander.new()
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should find command by label and start it, if found" do
|
25
|
-
invoker_config.stubs(:processes).returns([OpenStruct.new(:label => "resque", :cmd => "foo", :dir => "bar")])
|
26
|
-
invoker_config.expects(:process).returns(OpenStruct.new(:label => "resque", :cmd => "foo", :dir => "bar"))
|
27
|
-
@commander.expects(:add_command).returns(true)
|
28
|
-
|
29
|
-
@commander.add_command_by_label("resque")
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should not start already running process" do
|
33
|
-
@commander.workers.expects(:[]).returns(OpenStruct.new(:pid => "bogus"))
|
34
|
-
expect(@commander.add_command_by_label("resque")).to be_false
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "#remove_command" do
|
39
|
-
describe "when a worker is found" do
|
18
|
+
describe "#start_process" do
|
19
|
+
describe "when not daemonized" do
|
40
20
|
before do
|
41
|
-
|
42
|
-
|
21
|
+
invoker_config.stubs(:processes).returns(
|
22
|
+
[OpenStruct.new(:label => "foobar", :cmd => "foobar_command", :dir => ENV['HOME'])]
|
23
|
+
)
|
24
|
+
@commander = Invoker::Commander.new
|
25
|
+
Invoker.commander = @commander
|
43
26
|
end
|
44
27
|
|
45
|
-
|
46
|
-
|
47
|
-
@commander.expects(:process_kill).with("bogus", "HUP").returns(true)
|
48
|
-
expect(@commander.remove_command("resque", "HUP")).to be_true
|
49
|
-
end
|
28
|
+
after do
|
29
|
+
Invoker.commander = nil
|
50
30
|
end
|
51
31
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
32
|
+
it "should populate workers and open_pipes" do
|
33
|
+
@commander.expects(:start_event_loop)
|
34
|
+
@commander.process_manager.expects(:load_env).returns({})
|
35
|
+
@commander.process_manager.expects(:spawn).returns(100)
|
36
|
+
@commander.process_manager.expects(:wait_on_pid)
|
37
|
+
@commander.expects(:at_exit)
|
38
|
+
@commander.start_manager
|
39
|
+
expect(@commander.process_manager.open_pipes).not_to be_empty
|
40
|
+
expect(@commander.process_manager.workers).not_to be_empty
|
58
41
|
|
59
|
-
|
60
|
-
# before do
|
61
|
-
# @commander = Invoker::Commander.new()
|
62
|
-
# @commander.workers.expects(:[]).returns(OpenStruct.new(:pid => "bogus"))
|
63
|
-
# end
|
42
|
+
worker = @commander.process_manager.workers['foobar']
|
64
43
|
|
65
|
-
|
44
|
+
expect(worker).not_to be_nil
|
45
|
+
expect(worker.command_label).to eq('foobar')
|
66
46
|
|
67
|
-
|
68
|
-
|
47
|
+
pipe_end_worker = @commander.process_manager.open_pipes[worker.pipe_end.fileno]
|
48
|
+
expect(pipe_end_worker).not_to be_nil
|
49
|
+
end
|
69
50
|
end
|
70
51
|
|
71
|
-
describe "when
|
52
|
+
describe "when daemonized" do
|
72
53
|
before do
|
73
|
-
|
74
|
-
|
54
|
+
invoker_config.stubs(:processes).returns(
|
55
|
+
[OpenStruct.new(:label => "foobar", :cmd => "foobar_command", :dir => ENV['HOME'])]
|
56
|
+
)
|
57
|
+
@commander = Invoker::Commander.new
|
58
|
+
Invoker.commander = @commander
|
59
|
+
Invoker.daemonize = true
|
75
60
|
end
|
76
61
|
|
77
|
-
|
78
|
-
|
79
|
-
|
62
|
+
after do
|
63
|
+
Invoker.commander = nil
|
64
|
+
Invoker.daemonize = false
|
80
65
|
end
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
describe "#add_command" do
|
86
|
-
before do
|
87
|
-
invoker_config.stubs(:processes).returns([OpenStruct.new(:label => "sleep", :cmd => "sleep 4", :dir => ENV['HOME'])])
|
88
|
-
@commander = Invoker::Commander.new()
|
89
|
-
Invoker.const_set(:COMMANDER, @commander)
|
90
|
-
end
|
91
66
|
|
92
|
-
|
93
|
-
|
94
|
-
|
67
|
+
it "should daemonize the process and populate workers and open_pipes" do
|
68
|
+
@commander.expects(:start_event_loop)
|
69
|
+
@commander.process_manager.expects(:load_env).returns({})
|
70
|
+
Invoker.daemon.expects(:start).once
|
71
|
+
@commander.process_manager.expects(:spawn).returns(100)
|
72
|
+
@commander.process_manager.expects(:wait_on_pid)
|
73
|
+
@commander.expects(:at_exit)
|
74
|
+
@commander.start_manager
|
95
75
|
|
96
|
-
|
97
|
-
|
98
|
-
@commander.expects(:load_env).returns({})
|
99
|
-
@commander.start_manager()
|
100
|
-
expect(@commander.open_pipes).not_to be_empty
|
101
|
-
expect(@commander.workers).not_to be_empty
|
76
|
+
expect(@commander.process_manager.open_pipes).not_to be_empty
|
77
|
+
expect(@commander.process_manager.workers).not_to be_empty
|
102
78
|
|
103
|
-
|
79
|
+
worker = @commander.process_manager.workers['foobar']
|
104
80
|
|
105
|
-
|
106
|
-
|
107
|
-
expect(worker.color).to eq(:green)
|
81
|
+
expect(worker).not_to be_nil
|
82
|
+
expect(worker.command_label).to eq('foobar')
|
108
83
|
|
109
|
-
|
110
|
-
|
84
|
+
pipe_end_worker = @commander.process_manager.open_pipes[worker.pipe_end.fileno]
|
85
|
+
expect(pipe_end_worker).not_to be_nil
|
86
|
+
end
|
111
87
|
end
|
112
88
|
end
|
113
89
|
|
114
90
|
describe "#runnables" do
|
115
91
|
before do
|
116
|
-
@commander = Invoker::Commander.new
|
92
|
+
@commander = Invoker::Commander.new
|
117
93
|
end
|
118
94
|
|
119
95
|
it "should run runnables in reactor tick with one argument" do
|
120
|
-
@commander.on_next_tick("foo") { |cmd|
|
121
|
-
@commander.expects(:
|
96
|
+
@commander.on_next_tick("foo") { |cmd| start_process_by_name(cmd) }
|
97
|
+
@commander.expects(:start_process_by_name).returns(true)
|
122
98
|
@commander.run_runnables()
|
123
99
|
end
|
124
100
|
|
125
101
|
it "should run runnables with multiple args" do
|
126
102
|
@commander.on_next_tick("foo", "bar", "baz") { |t1,*rest|
|
127
|
-
|
103
|
+
stop_process(t1, rest)
|
128
104
|
}
|
129
|
-
@commander.expects(:
|
105
|
+
@commander.expects(:stop_process).with("foo", ["bar", "baz"]).returns(true)
|
130
106
|
@commander.run_runnables()
|
131
107
|
end
|
132
108
|
|
@@ -136,50 +112,4 @@ describe "Invoker::Commander" do
|
|
136
112
|
@commander.run_runnables()
|
137
113
|
end
|
138
114
|
end
|
139
|
-
|
140
|
-
describe "#load_env" do
|
141
|
-
before do
|
142
|
-
@commander = Invoker::Commander.new()
|
143
|
-
end
|
144
|
-
|
145
|
-
it "should load .env file from the specified directory" do
|
146
|
-
dir = "/tmp"
|
147
|
-
begin
|
148
|
-
env_file = File.new("#{dir}/.env", "w")
|
149
|
-
env_data =<<-EOD
|
150
|
-
FOO=foo
|
151
|
-
BAR=bar
|
152
|
-
EOD
|
153
|
-
env_file.write(env_data)
|
154
|
-
env_file.close
|
155
|
-
env_options = @commander.load_env(dir)
|
156
|
-
expect(env_options).to include("FOO" => "foo", "BAR" => "bar")
|
157
|
-
ensure
|
158
|
-
File.delete(env_file.path)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
it "should default to current directory if no directory is specified" do
|
163
|
-
dir = ENV["HOME"]
|
164
|
-
ENV.stubs(:[]).with("PWD").returns(dir)
|
165
|
-
begin
|
166
|
-
env_file = File.new("#{dir}/.env", "w")
|
167
|
-
env_data =<<-EOD
|
168
|
-
FOO=bar
|
169
|
-
BAR=foo
|
170
|
-
EOD
|
171
|
-
env_file.write(env_data)
|
172
|
-
env_file.close
|
173
|
-
env_options = @commander.load_env
|
174
|
-
expect(env_options).to include("FOO" => "bar", "BAR" => "foo")
|
175
|
-
ensure
|
176
|
-
File.delete(env_file.path)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
it "should return empty hash if there is no .env file" do
|
181
|
-
dir = "/tmp"
|
182
|
-
expect(@commander.load_env(dir)).to eq({})
|
183
|
-
end
|
184
|
-
end
|
185
115
|
end
|