itrg-invoker 1.6.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.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/bin/invoker +7 -0
  3. data/lib/invoker/cli/pinger.rb +23 -0
  4. data/lib/invoker/cli/question.rb +15 -0
  5. data/lib/invoker/cli/tail.rb +34 -0
  6. data/lib/invoker/cli/tail_watcher.rb +34 -0
  7. data/lib/invoker/cli.rb +197 -0
  8. data/lib/invoker/command_worker.rb +64 -0
  9. data/lib/invoker/commander.rb +101 -0
  10. data/lib/invoker/daemon.rb +126 -0
  11. data/lib/invoker/dns_cache.rb +23 -0
  12. data/lib/invoker/errors.rb +17 -0
  13. data/lib/invoker/event/manager.rb +79 -0
  14. data/lib/invoker/ipc/add_command.rb +12 -0
  15. data/lib/invoker/ipc/add_http_command.rb +10 -0
  16. data/lib/invoker/ipc/base_command.rb +24 -0
  17. data/lib/invoker/ipc/client_handler.rb +26 -0
  18. data/lib/invoker/ipc/dns_check_command.rb +17 -0
  19. data/lib/invoker/ipc/list_command.rb +11 -0
  20. data/lib/invoker/ipc/message/list_response.rb +35 -0
  21. data/lib/invoker/ipc/message/tail_response.rb +10 -0
  22. data/lib/invoker/ipc/message.rb +170 -0
  23. data/lib/invoker/ipc/ping_command.rb +10 -0
  24. data/lib/invoker/ipc/reload_command.rb +12 -0
  25. data/lib/invoker/ipc/remove_command.rb +12 -0
  26. data/lib/invoker/ipc/server.rb +26 -0
  27. data/lib/invoker/ipc/tail_command.rb +11 -0
  28. data/lib/invoker/ipc/unix_client.rb +60 -0
  29. data/lib/invoker/ipc.rb +45 -0
  30. data/lib/invoker/logger.rb +13 -0
  31. data/lib/invoker/parsers/config.rb +184 -0
  32. data/lib/invoker/parsers/procfile.rb +86 -0
  33. data/lib/invoker/power/balancer.rb +133 -0
  34. data/lib/invoker/power/config.rb +77 -0
  35. data/lib/invoker/power/dns.rb +38 -0
  36. data/lib/invoker/power/http_parser.rb +68 -0
  37. data/lib/invoker/power/http_response.rb +81 -0
  38. data/lib/invoker/power/port_finder.rb +49 -0
  39. data/lib/invoker/power/power.rb +3 -0
  40. data/lib/invoker/power/powerup.rb +29 -0
  41. data/lib/invoker/power/setup/distro/arch.rb +15 -0
  42. data/lib/invoker/power/setup/distro/base.rb +80 -0
  43. data/lib/invoker/power/setup/distro/debian.rb +11 -0
  44. data/lib/invoker/power/setup/distro/opensuse.rb +11 -0
  45. data/lib/invoker/power/setup/distro/redhat.rb +11 -0
  46. data/lib/invoker/power/setup/distro/ubuntu.rb +46 -0
  47. data/lib/invoker/power/setup/files/invoker_forwarder.sh.erb +17 -0
  48. data/lib/invoker/power/setup/files/socat_invoker.service +12 -0
  49. data/lib/invoker/power/setup/linux_setup.rb +97 -0
  50. data/lib/invoker/power/setup/osx_setup.rb +137 -0
  51. data/lib/invoker/power/setup.rb +93 -0
  52. data/lib/invoker/power/templates/400.html +40 -0
  53. data/lib/invoker/power/templates/404.html +40 -0
  54. data/lib/invoker/power/templates/503.html +40 -0
  55. data/lib/invoker/power/url_rewriter.rb +40 -0
  56. data/lib/invoker/process_manager.rb +201 -0
  57. data/lib/invoker/process_printer.rb +59 -0
  58. data/lib/invoker/reactor/reader.rb +65 -0
  59. data/lib/invoker/reactor.rb +37 -0
  60. data/lib/invoker/version.rb +47 -0
  61. data/lib/invoker.rb +151 -0
  62. data/spec/invoker/cli/pinger_spec.rb +22 -0
  63. data/spec/invoker/cli/tail_watcher_spec.rb +39 -0
  64. data/spec/invoker/cli_spec.rb +27 -0
  65. data/spec/invoker/command_worker_spec.rb +45 -0
  66. data/spec/invoker/commander_spec.rb +152 -0
  67. data/spec/invoker/config_spec.rb +361 -0
  68. data/spec/invoker/daemon_spec.rb +34 -0
  69. data/spec/invoker/event/manager_spec.rb +67 -0
  70. data/spec/invoker/invoker_spec.rb +71 -0
  71. data/spec/invoker/ipc/client_handler_spec.rb +54 -0
  72. data/spec/invoker/ipc/dns_check_command_spec.rb +32 -0
  73. data/spec/invoker/ipc/message/list_response_spec.rb +24 -0
  74. data/spec/invoker/ipc/message_spec.rb +49 -0
  75. data/spec/invoker/ipc/unix_client_spec.rb +29 -0
  76. data/spec/invoker/power/balancer_spec.rb +53 -0
  77. data/spec/invoker/power/config_spec.rb +18 -0
  78. data/spec/invoker/power/http_parser_spec.rb +32 -0
  79. data/spec/invoker/power/http_response_spec.rb +34 -0
  80. data/spec/invoker/power/port_finder_spec.rb +16 -0
  81. data/spec/invoker/power/setup/linux_setup_spec.rb +166 -0
  82. data/spec/invoker/power/setup/osx_setup_spec.rb +105 -0
  83. data/spec/invoker/power/setup_spec.rb +4 -0
  84. data/spec/invoker/power/url_rewriter_spec.rb +69 -0
  85. data/spec/invoker/power/web_sockets_spec.rb +61 -0
  86. data/spec/invoker/process_manager_spec.rb +130 -0
  87. data/spec/invoker/reactor_spec.rb +6 -0
  88. data/spec/spec_helper.rb +43 -0
  89. metadata +376 -0
@@ -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
@@ -0,0 +1,361 @@
1
+ require "spec_helper"
2
+
3
+ require "tempfile"
4
+
5
+ describe "Invoker::Config" do
6
+ describe "with invalid directory" do
7
+ it "should raise error during startup" do
8
+ begin
9
+ file = Tempfile.new(["invalid_config", ".ini"])
10
+
11
+ config_data =<<-EOD
12
+ [try_sleep]
13
+ directory = /Users/gnufied/foo
14
+ command = ruby try_sleep.rb
15
+ EOD
16
+ file.write(config_data)
17
+ file.close
18
+ expect {
19
+ Invoker::Parsers::Config.new(file.path, 9000)
20
+ }.to raise_error(Invoker::Errors::InvalidConfig)
21
+ ensure
22
+ file.unlink()
23
+ end
24
+ end
25
+ end
26
+
27
+ describe "with relative directory path" do
28
+ it "should expand path in commands" do
29
+ begin
30
+ file = Tempfile.new(["config", ".ini"])
31
+
32
+ config_data =<<-EOD
33
+ [pwd_home]
34
+ directory = ~
35
+ command = pwd
36
+
37
+ [pwd_parent]
38
+ directory = ../
39
+ command = pwd
40
+ EOD
41
+ file.write(config_data)
42
+ file.close
43
+
44
+ config = Invoker::Parsers::Config.new(file.path, 9000)
45
+ command1 = config.processes.first
46
+
47
+ expect(command1.dir).to match(File.expand_path('~'))
48
+
49
+ command2 = config.processes[1]
50
+
51
+ expect(command2.dir).to match(File.expand_path('..'))
52
+ ensure
53
+ file.unlink()
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "for ports" do
59
+ it "should replace port in commands" do
60
+ begin
61
+ file = Tempfile.new(["invalid_config", ".ini"])
62
+
63
+ config_data =<<-EOD
64
+ [try_sleep]
65
+ directory = /tmp
66
+ command = ruby try_sleep.rb -p $PORT
67
+
68
+ [ls]
69
+ directory = /tmp
70
+ command = ls -p $PORT
71
+
72
+ [noport]
73
+ directory = /tmp
74
+ command = ls
75
+ EOD
76
+ file.write(config_data)
77
+ file.close
78
+
79
+ config = Invoker::Parsers::Config.new(file.path, 9000)
80
+ command1 = config.processes.first
81
+
82
+ expect(command1.port).to eq(9000)
83
+ expect(command1.cmd).to match(/9000/)
84
+
85
+ command2 = config.processes[1]
86
+
87
+ expect(command2.port).to eq(9001)
88
+ expect(command2.cmd).to match(/9001/)
89
+
90
+ command2 = config.processes[2]
91
+
92
+ expect(command2.port).to be_nil
93
+ ensure
94
+ file.unlink()
95
+ end
96
+ end
97
+
98
+ it "should use port from separate option" do
99
+ begin
100
+ file = Tempfile.new(["invalid_config", ".ini"])
101
+ config_data =<<-EOD
102
+ [try_sleep]
103
+ directory = /tmp
104
+ command = ruby try_sleep.rb -p $PORT
105
+
106
+ [ls]
107
+ directory = /tmp
108
+ port = 3000
109
+ command = pwd
110
+
111
+ [noport]
112
+ directory = /tmp
113
+ command = ls
114
+ EOD
115
+ file.write(config_data)
116
+ file.close
117
+
118
+ config = Invoker::Parsers::Config.new(file.path, 9000)
119
+ command1 = config.processes.first
120
+
121
+ expect(command1.port).to eq(9000)
122
+ expect(command1.cmd).to match(/9000/)
123
+
124
+ command2 = config.processes[1]
125
+
126
+ expect(command2.port).to eq(3000)
127
+
128
+ command2 = config.processes[2]
129
+
130
+ expect(command2.port).to be_nil
131
+ ensure
132
+ file.unlink()
133
+ end
134
+ end
135
+ end
136
+
137
+ describe "loading power config", fakefs: true do
138
+ before do
139
+ FileUtils.mkdir_p('/tmp')
140
+ FileUtils.mkdir_p(inv_conf_dir)
141
+ File.open("/tmp/foo.ini", "w") { |fl| fl.write("") }
142
+ end
143
+
144
+ it "does not load config if platform is darwin but there is no power config file" do
145
+ Invoker::Power::Config.expects(:load_config).never
146
+ Invoker::Parsers::Config.new("/tmp/foo.ini", 9000)
147
+ end
148
+
149
+ it "loads config if platform is darwin and power config file exists" do
150
+ File.open(Invoker::Power::Config.config_file, "w") { |fl| fl.puts "sample" }
151
+ Invoker::Power::Config.expects(:load_config).once
152
+ Invoker::Parsers::Config.new("/tmp/foo.ini", 9000)
153
+ end
154
+ end
155
+
156
+ describe "Procfile" do
157
+ it "should load Procfiles and create config object" do
158
+ File.open("/tmp/Procfile", "w") {|fl|
159
+ fl.write <<-EOD
160
+ web: bundle exec rails s -p $PORT
161
+ EOD
162
+ }
163
+ config = Invoker::Parsers::Config.new("/tmp/Procfile", 9000)
164
+ command1 = config.processes.first
165
+
166
+ expect(command1.port).to eq(9000)
167
+ expect(command1.cmd).to match(/bundle exec rails/)
168
+ end
169
+ end
170
+
171
+ describe "Copy of DNS information" do
172
+ it "should allow copy of DNS information" do
173
+ File.open("/tmp/Procfile", "w") {|fl|
174
+ fl.write <<-EOD
175
+ web: bundle exec rails s -p $PORT
176
+ EOD
177
+ }
178
+ Invoker.load_invoker_config("/tmp/Procfile", 9000)
179
+ dns_cache = Invoker::DNSCache.new(Invoker.config)
180
+
181
+ expect(dns_cache.dns_data).to_not be_empty
182
+ expect(dns_cache.dns_data['web']).to_not be_empty
183
+ expect(dns_cache.dns_data['web']['port']).to eql 9000
184
+ end
185
+ end
186
+
187
+ describe "#autorunnable_processes" do
188
+ it "returns a list of processes that can be autorun" do
189
+ begin
190
+ file = Tempfile.new(["config", ".ini"])
191
+ config_data =<<-EOD
192
+ [postgres]
193
+ command = postgres -D /usr/local/var/postgres
194
+
195
+ [redis]
196
+ command = redis-server /usr/local/etc/redis.conf
197
+ disable_autorun = true
198
+
199
+ [memcached]
200
+ command = /usr/local/opt/memcached/bin/memcached
201
+ disable_autorun = false
202
+
203
+ [panda-api]
204
+ command = bundle exec rails s
205
+ disable_autorun = true
206
+
207
+ [panda-auth]
208
+ command = bundle exec rails s -p $PORT
209
+ EOD
210
+ file.write(config_data)
211
+ file.close
212
+
213
+ config = Invoker::Parsers::Config.new(file.path, 9000)
214
+ expect(config.autorunnable_processes.map(&:label)).to eq(['postgres', 'memcached', 'panda-auth'])
215
+ ensure
216
+ file.unlink()
217
+ end
218
+ end
219
+
220
+ it "returns a list of processes that can by index" do
221
+ begin
222
+ file = Tempfile.new(["config", ".ini"])
223
+ config_data =<<-EOD
224
+ [postgres]
225
+ command = postgres -D /usr/local/var/postgres
226
+ index = 2
227
+ sleep = 5
228
+
229
+ [redis]
230
+ command = redis-server /usr/local/etc/redis.conf
231
+ disable_autorun = true
232
+ index = 3
233
+
234
+ [memcached]
235
+ command = /usr/local/opt/memcached/bin/memcached
236
+ disable_autorun = false
237
+ index = 5
238
+
239
+ [panda-api]
240
+ command = bundle exec rails s
241
+ disable_autorun = true
242
+ index = 4
243
+
244
+ [panda-auth]
245
+ command = bundle exec rails s -p $PORT
246
+ index = 1
247
+ EOD
248
+ file.write(config_data)
249
+ file.close
250
+
251
+ config = Invoker::Parsers::Config.new(file.path, 9000)
252
+ processes = config.autorunnable_processes
253
+ expect(processes.map(&:label)).to eq(['panda-auth', 'postgres', 'memcached'])
254
+ expect(processes[0].sleep_duration).to eq(0)
255
+ expect(processes[1].sleep_duration).to eq(5)
256
+ ensure
257
+ file.unlink()
258
+ end
259
+ end
260
+ end
261
+
262
+ describe "global config file" do
263
+ it "should use global config file if available" do
264
+ begin
265
+ FileUtils.mkdir_p(Invoker::Power::Config.config_dir)
266
+ filename = "#{Invoker::Power::Config.config_dir}/foo.ini"
267
+ file = File.open(filename, "w")
268
+ config_data =<<-EOD
269
+ [try_sleep]
270
+ directory = /tmp
271
+ command = ruby try_sleep.rb
272
+ EOD
273
+ file.write(config_data)
274
+ file.close
275
+ config = Invoker::Parsers::Config.new("foo", 9000)
276
+ expect(config.filename).to eql(filename)
277
+ ensure
278
+ File.unlink(filename)
279
+ end
280
+ end
281
+ end
282
+
283
+ describe "config file autodetection" do
284
+ context "no config file given" do
285
+
286
+ def create_invoker_ini
287
+ file = File.open("invoker.ini", "w")
288
+ config_data =<<-EOD
289
+ [some_process]
290
+ command = some_command
291
+ EOD
292
+ file.write(config_data)
293
+ file.close
294
+
295
+ file
296
+ end
297
+
298
+ def create_procfile
299
+ file = File.open("Procfile", "w")
300
+ config_data =<<-EOD
301
+ some_other_process: some_other_command
302
+ EOD
303
+ file.write(config_data)
304
+ file.close
305
+
306
+ file
307
+ end
308
+
309
+ context "directory has invoker.ini" do
310
+ it "autodetects invoker.ini" do
311
+ begin
312
+ file = create_invoker_ini
313
+
314
+ config = Invoker::Parsers::Config.new(nil, 9000)
315
+ expect(config.process("some_process").cmd).to eq("some_command")
316
+ ensure
317
+ File.delete(file)
318
+ end
319
+ end
320
+ end
321
+
322
+ context "directory has Procfile" do
323
+ it "autodetects Procfile" do
324
+ begin
325
+ file = create_procfile
326
+
327
+ config = Invoker::Parsers::Config.new(nil, 9000)
328
+ expect(config.process("some_other_process").cmd).to eq("some_other_command")
329
+ ensure
330
+ File.delete(file)
331
+ end
332
+ end
333
+ end
334
+
335
+ context "directory has both invoker.ini and Procfile" do
336
+ it "prioritizes invoker.ini" do
337
+ begin
338
+ invoker_ini = create_invoker_ini
339
+ procfile = create_procfile
340
+
341
+ config = Invoker::Parsers::Config.new(nil, 9000)
342
+ expect(config.process("some_process").cmd).to eq("some_command")
343
+ processes = config.autorunnable_processes
344
+ process_1 = processes[0]
345
+ expect(process_1.sleep_duration).to eq(0)
346
+ expect(process_1.index).to eq(0)
347
+ ensure
348
+ File.delete(invoker_ini)
349
+ File.delete(procfile)
350
+ end
351
+ end
352
+ end
353
+
354
+ context "directory doesn't have invoker.ini or Procfile" do
355
+ it "aborts" do
356
+ expect { Invoker::Parsers::Config.new(nil, 9000) }.to raise_error(SystemExit)
357
+ end
358
+ end
359
+ end
360
+ end
361
+ end
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ describe Invoker::Daemon do
4
+ let(:daemon) { Invoker::Daemon.new}
5
+
6
+ describe "#start" do
7
+ context "when daemon is aleady running" do
8
+ it "exits without any error" do
9
+ daemon.expects(:running?).returns(true)
10
+ begin
11
+ daemon.start
12
+ rescue SystemExit => e
13
+ expect(e.status).to be(0)
14
+ end
15
+ end
16
+ end
17
+
18
+ context "when daemon is not running" do
19
+ it "starts the daemon" do
20
+ daemon.expects(:dead?).returns(false)
21
+ daemon.expects(:running?).returns(false)
22
+ daemon.expects(:daemonize)
23
+ daemon.start
24
+ end
25
+ end
26
+ end
27
+
28
+ describe "#stop" do
29
+ it "stops the daemon" do
30
+ daemon.expects(:kill_process)
31
+ daemon.stop
32
+ end
33
+ end
34
+ end