invoker 1.3.2 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/contrib/completion/invoker-completion.bash +70 -0
- data/lib/invoker/cli.rb +2 -2
- data/lib/invoker/ipc/message.rb +1 -1
- data/lib/invoker/ipc/message/list_response.rb +4 -2
- data/lib/invoker/parsers/config.rb +38 -5
- data/lib/invoker/power/balancer.rb +7 -23
- data/lib/invoker/power/setup/distro/base.rb +6 -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/ubuntu.rb +3 -4
- data/lib/invoker/power/templates/400.html +40 -0
- data/lib/invoker/power/url_rewriter.rb +37 -0
- data/lib/invoker/process_printer.rb +1 -0
- data/lib/invoker/version.rb +1 -1
- data/spec/invoker/config_spec.rb +103 -8
- data/spec/invoker/ipc/message/list_response_spec.rb +4 -2
- data/spec/invoker/ipc/message_spec.rb +8 -4
- data/spec/invoker/power/balancer_spec.rb +11 -64
- data/spec/invoker/power/url_rewriter_spec.rb +38 -0
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d51eb067dec10fd3eefb72b5ddc023b147017a51
|
4
|
+
data.tar.gz: ff4b7b25c9558f5e718bf44b29b3e0aa42990579
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92c403e1bba997b4568dd7071c6649a7bce887e5a87d74c60158abb4c73c773362ed8310b6a73a695baf8d459758072b8f63662c3a96b3ec00d9486a5f5fa878
|
7
|
+
data.tar.gz: f6ae56c5bcba81cdb85528faa8e8f843fa324c9c08b82b61d14ba4151e9dd88eea2dfab6304925ff1398361e1dc9bef98cdf8453082c8e6d1aa64349626a15fd
|
data/.gitignore
CHANGED
@@ -0,0 +1,70 @@
|
|
1
|
+
# BASH completion function for Invoker
|
2
|
+
|
3
|
+
# source it from bashrc
|
4
|
+
# dependencies:
|
5
|
+
# 1) netcat
|
6
|
+
# 2) find
|
7
|
+
|
8
|
+
check_open_port()
|
9
|
+
{
|
10
|
+
local port=$1
|
11
|
+
if [[ $(which nc) ]]; then
|
12
|
+
local open=$(nc -z -w2 localhost $port > /dev/null; echo $?)
|
13
|
+
if [[ "$open" == "1" ]]; then
|
14
|
+
COMPREPLY=( $(compgen -W "${port}" -- ${cur}) )
|
15
|
+
else
|
16
|
+
check_open_port $(($port+1))
|
17
|
+
fi
|
18
|
+
fi
|
19
|
+
}
|
20
|
+
_invoker()
|
21
|
+
{
|
22
|
+
local cur prev opts
|
23
|
+
COMPREPLY=()
|
24
|
+
cur="${COMP_WORDS[COMP_CWORD]}"
|
25
|
+
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
26
|
+
opts="add add_http help list reload remove setup"
|
27
|
+
opts="$opts start stop tail uninstall version"
|
28
|
+
|
29
|
+
case "${prev}" in
|
30
|
+
add | add_http | list | reload | remove | setup | stop | tail \
|
31
|
+
| uninstall | version)
|
32
|
+
COMPREPLY=()
|
33
|
+
;;
|
34
|
+
-d | --daemon | --no-daemon)
|
35
|
+
local extra_opts=("--port")
|
36
|
+
COMPREPLY=( $(compgen -W "${extra_opts}" -- ${cur}) )
|
37
|
+
;;
|
38
|
+
--port)
|
39
|
+
# auto-suggest port
|
40
|
+
check_open_port 9000
|
41
|
+
;;
|
42
|
+
help)
|
43
|
+
# Show opts again, but only once; don't infinitely recurse
|
44
|
+
local prev2="${COMP_WORDS[COMP_CWORD-2]}"
|
45
|
+
if [ "$prev2" == "help" ]; then
|
46
|
+
COMPREPLY=()
|
47
|
+
else
|
48
|
+
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
49
|
+
fi
|
50
|
+
;;
|
51
|
+
start)
|
52
|
+
local filename=$(find . -type f -name "*.ini")
|
53
|
+
if [[ $filename ]]; then
|
54
|
+
COMPREPLY=( $(compgen -W "${filename}" -- ${cur}) )
|
55
|
+
else
|
56
|
+
COMPREPLY=()
|
57
|
+
fi
|
58
|
+
;;
|
59
|
+
*.ini)
|
60
|
+
local start_opts="-d --daemon --no-daemon --port"
|
61
|
+
COMPREPLY=( $(compgen -W "${start_opts}" -- ${cur}) )
|
62
|
+
;;
|
63
|
+
invoker)
|
64
|
+
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
65
|
+
;;
|
66
|
+
esac
|
67
|
+
|
68
|
+
return 0
|
69
|
+
}
|
70
|
+
complete -F _invoker invoker
|
data/lib/invoker/cli.rb
CHANGED
@@ -28,13 +28,13 @@ module Invoker
|
|
28
28
|
Invoker::Power::Setup.uninstall
|
29
29
|
end
|
30
30
|
|
31
|
-
desc "start CONFIG_FILE", "Start Invoker Server"
|
31
|
+
desc "start [CONFIG_FILE]", "Start Invoker Server"
|
32
32
|
option :port, type: :numeric, banner: "Port series to be used for starting rack servers"
|
33
33
|
option :daemon,
|
34
34
|
type: :boolean,
|
35
35
|
banner: "Daemonize the server into the background",
|
36
36
|
aliases: [:d]
|
37
|
-
def start(file)
|
37
|
+
def start(file = nil)
|
38
38
|
Invoker.setup_config_location
|
39
39
|
port = options[:port] || 9000
|
40
40
|
Invoker.daemonize = options[:daemon]
|
data/lib/invoker/ipc/message.rb
CHANGED
@@ -16,8 +16,10 @@ module Invoker
|
|
16
16
|
process_array = []
|
17
17
|
Invoker.config.processes.each do |process|
|
18
18
|
worker_attrs = {
|
19
|
-
:
|
20
|
-
:
|
19
|
+
shell_command: process.cmd,
|
20
|
+
process_name: process.label,
|
21
|
+
dir: process.dir,
|
22
|
+
port: process.port
|
21
23
|
}
|
22
24
|
if worker = workers[process.label]
|
23
25
|
worker_attrs.update(pid: worker.pid)
|
@@ -4,11 +4,22 @@ module Invoker
|
|
4
4
|
module Parsers
|
5
5
|
class Config
|
6
6
|
PORT_REGEX = /\$PORT/
|
7
|
-
attr_accessor :processes, :power_config
|
8
7
|
|
8
|
+
attr_accessor :processes, :power_config
|
9
|
+
attr_reader :filename
|
10
|
+
|
11
|
+
# initialize takes a port form cli and decrements it by 1 and sets the
|
12
|
+
# instance variable @port. This port value is used as the environment
|
13
|
+
# variable $PORT mentioned inside invoker.ini. When method pick_port gets
|
14
|
+
# fired it increments the value of port by 1, subsequently when pick_port
|
15
|
+
# again gets fired, for another command, it will again increment port
|
16
|
+
# value by 1, that way generating different ports for different commands.
|
9
17
|
def initialize(filename, port)
|
10
|
-
@filename = filename
|
11
|
-
|
18
|
+
@filename = filename || autodetect_config_file
|
19
|
+
|
20
|
+
print_message_and_abort if invalid_config_file?
|
21
|
+
|
22
|
+
@port = port - 1
|
12
23
|
@processes = load_config
|
13
24
|
if Invoker.can_run_balancer?
|
14
25
|
@power_config = Invoker::Power::Config.load_config()
|
@@ -37,14 +48,23 @@ module Invoker
|
|
37
48
|
|
38
49
|
private
|
39
50
|
|
51
|
+
def autodetect_config_file
|
52
|
+
Dir.glob("{invoker.ini,Procfile}").first
|
53
|
+
end
|
54
|
+
|
55
|
+
def invalid_config_file?
|
56
|
+
@filename.nil?
|
57
|
+
end
|
58
|
+
|
40
59
|
def load_config
|
60
|
+
@filename = to_global_file if is_global?
|
61
|
+
|
41
62
|
if is_ini?
|
42
63
|
process_ini
|
43
64
|
elsif is_procfile?
|
44
65
|
process_procfile
|
45
66
|
else
|
46
|
-
|
47
|
-
abort
|
67
|
+
print_message_and_abort
|
48
68
|
end
|
49
69
|
end
|
50
70
|
|
@@ -65,6 +85,11 @@ module Invoker
|
|
65
85
|
end
|
66
86
|
end
|
67
87
|
|
88
|
+
def print_message_and_abort
|
89
|
+
Invoker::Logger.puts("\n Invalid config file. Invoker requires an ini or a Procfile.".color(:red))
|
90
|
+
abort
|
91
|
+
end
|
92
|
+
|
68
93
|
def process_command_from_section(section)
|
69
94
|
if supports_subdomain?(section)
|
70
95
|
port = pick_port(section)
|
@@ -128,6 +153,14 @@ module Invoker
|
|
128
153
|
def is_procfile?
|
129
154
|
@filename =~ /Procfile/
|
130
155
|
end
|
156
|
+
|
157
|
+
def to_global_file
|
158
|
+
File.join(Invoker::Power::Config.config_dir, "#{@filename}.ini")
|
159
|
+
end
|
160
|
+
|
161
|
+
def is_global?
|
162
|
+
@filename =~ /^\w+$/ && File.exist?(to_global_file)
|
163
|
+
end
|
131
164
|
end
|
132
165
|
end
|
133
166
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'em-proxy'
|
2
2
|
require 'http-parser'
|
3
3
|
require "invoker/power/http_parser"
|
4
|
+
require "invoker/power/url_rewriter"
|
4
5
|
|
5
6
|
module Invoker
|
6
7
|
module Power
|
@@ -22,8 +23,6 @@ module Invoker
|
|
22
23
|
|
23
24
|
class Balancer
|
24
25
|
attr_accessor :connection, :http_parser, :session, :protocol
|
25
|
-
DEV_MATCH_REGEX = /([\w-]+)\.dev(\:\d+)?$/
|
26
|
-
XIP_IO_MATCH_REGEX = /([\w-]+)\.\d+\.\d+\.\d+\.\d+\.xip\.io(\:\d+)?$/
|
27
26
|
|
28
27
|
def self.run(options = {})
|
29
28
|
start_http_proxy(InvokerHttpProxy, 'http', options)
|
@@ -65,7 +64,12 @@ module Invoker
|
|
65
64
|
return
|
66
65
|
end
|
67
66
|
@session = UUID.generate()
|
68
|
-
|
67
|
+
if !headers['Host'] || headers['Host'].empty?
|
68
|
+
return_error_page(400)
|
69
|
+
return
|
70
|
+
end
|
71
|
+
|
72
|
+
dns_check_response = UrlRewriter.new.select_backend_config(headers['Host'])
|
69
73
|
if dns_check_response && dns_check_response.port
|
70
74
|
connection.server(session, host: '0.0.0.0', port: dns_check_response.port)
|
71
75
|
else
|
@@ -101,28 +105,8 @@ module Invoker
|
|
101
105
|
connection.close_connection_after_writing if backend == session
|
102
106
|
end
|
103
107
|
|
104
|
-
def extract_host_from_domain(host)
|
105
|
-
host.match(DEV_MATCH_REGEX) || host.match(XIP_IO_MATCH_REGEX)
|
106
|
-
end
|
107
|
-
|
108
108
|
private
|
109
109
|
|
110
|
-
def select_backend_config(host)
|
111
|
-
matching_string = extract_host_from_domain(host)
|
112
|
-
return nil unless matching_string
|
113
|
-
if selected_app = matching_string[1]
|
114
|
-
dns_check(process_name: selected_app)
|
115
|
-
else
|
116
|
-
nil
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def dns_check(dns_args)
|
121
|
-
Invoker::IPC::UnixClient.send_command("dns_check", dns_args) do |dns_response|
|
122
|
-
dns_response
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
110
|
def return_error_page(status)
|
127
111
|
http_response = Invoker::Power::HttpResponse.new()
|
128
112
|
http_response.status = status
|
@@ -16,6 +16,12 @@ module Invoker
|
|
16
16
|
when "Archlinux"
|
17
17
|
require "invoker/power/setup/distro/arch"
|
18
18
|
Arch.new
|
19
|
+
when "Debian"
|
20
|
+
require "invoker/power/setup/distro/debian"
|
21
|
+
Debian.new
|
22
|
+
when "LinuxMint"
|
23
|
+
require "invoker/power/setup/distro/mint"
|
24
|
+
Mint.new
|
19
25
|
else
|
20
26
|
raise "Your selected distro is not supported by Invoker"
|
21
27
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title>Invoker</title>
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
margin: 0;
|
9
|
+
padding: 0;
|
10
|
+
background: #fff;
|
11
|
+
line-height: 18px;
|
12
|
+
}
|
13
|
+
div.page {
|
14
|
+
padding: 36px 90px;
|
15
|
+
}
|
16
|
+
h1, h2, p, li {
|
17
|
+
font-family: Helvetica, sans-serif;
|
18
|
+
font-size: 13px;
|
19
|
+
}
|
20
|
+
h1 {
|
21
|
+
line-height: 45px;
|
22
|
+
font-size: 36px;
|
23
|
+
margin: 0;
|
24
|
+
}
|
25
|
+
h2 {
|
26
|
+
line-height: 27px;
|
27
|
+
font-size: 18px;
|
28
|
+
font-weight: normal;
|
29
|
+
margin: 0;
|
30
|
+
}
|
31
|
+
</style>
|
32
|
+
</head>
|
33
|
+
<body class="">
|
34
|
+
<div class="page">
|
35
|
+
<h1>Bad request</h1>
|
36
|
+
<hr>
|
37
|
+
<h2>Invoker couldn't understand the request</h2>
|
38
|
+
</div>
|
39
|
+
</body>
|
40
|
+
</html>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Invoker
|
2
|
+
module Power
|
3
|
+
class UrlRewriter
|
4
|
+
DEV_MATCH_REGEX = [/([\w.-]+)\.dev(\:\d+)?$/, /([\w-]+)\.dev(\:\d+)?$/]
|
5
|
+
|
6
|
+
def select_backend_config(complete_path)
|
7
|
+
possible_matches = extract_host_from_domain(complete_path)
|
8
|
+
exact_match = nil
|
9
|
+
possible_matches.each do |match|
|
10
|
+
if match
|
11
|
+
exact_match = dns_check(process_name: match)
|
12
|
+
break if exact_match.port
|
13
|
+
end
|
14
|
+
end
|
15
|
+
exact_match
|
16
|
+
end
|
17
|
+
|
18
|
+
def extract_host_from_domain(complete_path)
|
19
|
+
matching_strings = []
|
20
|
+
DEV_MATCH_REGEX.map do |regexp|
|
21
|
+
if (match_result = complete_path.match(regexp))
|
22
|
+
matching_strings << match_result[1]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
matching_strings.uniq
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def dns_check(dns_args)
|
31
|
+
Invoker::IPC::UnixClient.send_command("dns_check", dns_args) do |dns_response|
|
32
|
+
dns_response
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -26,6 +26,7 @@ module Invoker
|
|
26
26
|
|
27
27
|
hash_with_colors['dir'] = colored_string(process.dir, color)
|
28
28
|
hash_with_colors['pid'] = colored_string(process.pid || 'Not Running', color)
|
29
|
+
hash_with_colors['port'] = colored_string(process.port, color)
|
29
30
|
hash_with_colors['shell_command'] = colored_string(process.shell_command, color)
|
30
31
|
hash_with_colors['process_name'] = colored_string(process.process_name, color)
|
31
32
|
hash_with_colors
|
data/lib/invoker/version.rb
CHANGED
data/spec/invoker/config_spec.rb
CHANGED
@@ -79,13 +79,13 @@ command = ls
|
|
79
79
|
config = Invoker::Parsers::Config.new(file.path, 9000)
|
80
80
|
command1 = config.processes.first
|
81
81
|
|
82
|
-
expect(command1.port).to eq(
|
83
|
-
expect(command1.cmd).to match(/
|
82
|
+
expect(command1.port).to eq(9000)
|
83
|
+
expect(command1.cmd).to match(/9000/)
|
84
84
|
|
85
85
|
command2 = config.processes[1]
|
86
86
|
|
87
|
-
expect(command2.port).to eq(
|
88
|
-
expect(command2.cmd).to match(/
|
87
|
+
expect(command2.port).to eq(9001)
|
88
|
+
expect(command2.cmd).to match(/9001/)
|
89
89
|
|
90
90
|
command2 = config.processes[2]
|
91
91
|
|
@@ -118,8 +118,8 @@ command = ls
|
|
118
118
|
config = Invoker::Parsers::Config.new(file.path, 9000)
|
119
119
|
command1 = config.processes.first
|
120
120
|
|
121
|
-
expect(command1.port).to eq(
|
122
|
-
expect(command1.cmd).to match(/
|
121
|
+
expect(command1.port).to eq(9000)
|
122
|
+
expect(command1.cmd).to match(/9000/)
|
123
123
|
|
124
124
|
command2 = config.processes[1]
|
125
125
|
|
@@ -162,7 +162,7 @@ web: bundle exec rails s -p $PORT
|
|
162
162
|
config = Invoker::Parsers::Config.new("/tmp/Procfile", 9000)
|
163
163
|
command1 = config.processes.first
|
164
164
|
|
165
|
-
expect(command1.port).to eq(
|
165
|
+
expect(command1.port).to eq(9000)
|
166
166
|
expect(command1.cmd).to match(/bundle exec rails/)
|
167
167
|
ensure
|
168
168
|
File.delete("/tmp/Procfile")
|
@@ -183,7 +183,7 @@ web: bundle exec rails s -p $PORT
|
|
183
183
|
|
184
184
|
expect(dns_cache.dns_data).to_not be_empty
|
185
185
|
expect(dns_cache.dns_data['web']).to_not be_empty
|
186
|
-
expect(dns_cache.dns_data['web']['port']).to eql
|
186
|
+
expect(dns_cache.dns_data['web']['port']).to eql 9000
|
187
187
|
ensure
|
188
188
|
File.delete("/tmp/Procfile")
|
189
189
|
end
|
@@ -223,4 +223,99 @@ command = bundle exec rails s -p $PORT
|
|
223
223
|
end
|
224
224
|
end
|
225
225
|
end
|
226
|
+
|
227
|
+
describe "global config file" do
|
228
|
+
it "should use global config file if available" do
|
229
|
+
begin
|
230
|
+
filename = "#{Invoker::Power::Config.config_dir}/foo.ini"
|
231
|
+
file = File.open(filename, "w")
|
232
|
+
config_data =<<-EOD
|
233
|
+
[try_sleep]
|
234
|
+
directory = /tmp
|
235
|
+
command = ruby try_sleep.rb
|
236
|
+
EOD
|
237
|
+
file.write(config_data)
|
238
|
+
file.close
|
239
|
+
config = Invoker::Parsers::Config.new("foo", 9000)
|
240
|
+
expect(config.filename).to eql(filename)
|
241
|
+
ensure
|
242
|
+
File.unlink(filename)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe "config file autodetection" do
|
248
|
+
context "no config file given" do
|
249
|
+
|
250
|
+
def create_invoker_ini
|
251
|
+
file = File.open("invoker.ini", "w")
|
252
|
+
config_data =<<-EOD
|
253
|
+
[some_process]
|
254
|
+
command = some_command
|
255
|
+
EOD
|
256
|
+
file.write(config_data)
|
257
|
+
file.close
|
258
|
+
|
259
|
+
file
|
260
|
+
end
|
261
|
+
|
262
|
+
def create_procfile
|
263
|
+
file = File.open("Procfile", "w")
|
264
|
+
config_data =<<-EOD
|
265
|
+
some_other_process: some_other_command
|
266
|
+
EOD
|
267
|
+
file.write(config_data)
|
268
|
+
file.close
|
269
|
+
|
270
|
+
file
|
271
|
+
end
|
272
|
+
|
273
|
+
context "directory has invoker.ini" do
|
274
|
+
it "autodetects invoker.ini" do
|
275
|
+
begin
|
276
|
+
file = create_invoker_ini
|
277
|
+
|
278
|
+
config = Invoker::Parsers::Config.new(nil, 9000)
|
279
|
+
expect(config.process("some_process").cmd).to eq("some_command")
|
280
|
+
ensure
|
281
|
+
File.delete(file)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
context "directory has Procfile" do
|
287
|
+
it "autodetects Procfile" do
|
288
|
+
begin
|
289
|
+
file = create_procfile
|
290
|
+
|
291
|
+
config = Invoker::Parsers::Config.new(nil, 9000)
|
292
|
+
expect(config.process("some_other_process").cmd).to eq("some_other_command")
|
293
|
+
ensure
|
294
|
+
File.delete(file)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
context "directory has both invoker.ini and Procfile" do
|
300
|
+
it "prioritizes invoker.ini" do
|
301
|
+
begin
|
302
|
+
invoker_ini = create_invoker_ini
|
303
|
+
procfile = create_procfile
|
304
|
+
|
305
|
+
config = Invoker::Parsers::Config.new(nil, 9000)
|
306
|
+
expect(config.process("some_process").cmd).to eq("some_command")
|
307
|
+
ensure
|
308
|
+
File.delete(invoker_ini)
|
309
|
+
File.delete(procfile)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context "directory doesn't have invoker.ini or Procfile" do
|
315
|
+
it "aborts" do
|
316
|
+
expect { Invoker::Parsers::Config.new(nil, 9000) }.to raise_error(SystemExit)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
226
321
|
end
|
@@ -4,8 +4,10 @@ describe MM::ListResponse do
|
|
4
4
|
context "serializing a response" do
|
5
5
|
let(:process_array) do
|
6
6
|
[
|
7
|
-
{ shell_command: 'foo', process_name: 'foo', dir: '/tmp', pid: 100
|
8
|
-
|
7
|
+
{ shell_command: 'foo', process_name: 'foo', dir: '/tmp', pid: 100,
|
8
|
+
port: 9000 },
|
9
|
+
{ shell_command: 'bar', process_name: 'bar', dir: '/tmp', pid: 200,
|
10
|
+
port: 9001 }
|
9
11
|
]
|
10
12
|
end
|
11
13
|
|
@@ -19,8 +19,10 @@ describe Invoker::IPC::Message do
|
|
19
19
|
context "for nested messages" do
|
20
20
|
let(:process_array) do
|
21
21
|
[
|
22
|
-
{ shell_command: 'foo', process_name: 'foo', dir: '/tmp', pid: 100
|
23
|
-
|
22
|
+
{ shell_command: 'foo', process_name: 'foo', dir: '/tmp', pid: 100,
|
23
|
+
port: 9000 },
|
24
|
+
{ shell_command: 'bar', process_name: 'bar', dir: '/tmp', pid: 200,
|
25
|
+
port: 9001 }
|
24
26
|
]
|
25
27
|
end
|
26
28
|
|
@@ -33,8 +35,10 @@ describe Invoker::IPC::Message do
|
|
33
35
|
|
34
36
|
it "should report not equal for different objects" do
|
35
37
|
another_process_array = [
|
36
|
-
{ shell_command: 'baz', process_name: 'foo', dir: '/tmp', pid: 100
|
37
|
-
|
38
|
+
{ shell_command: 'baz', process_name: 'foo', dir: '/tmp', pid: 100,
|
39
|
+
port: 9000 },
|
40
|
+
{ shell_command: 'bar', process_name: 'bar', dir: '/tmp', pid: 200,
|
41
|
+
port: 9001 }
|
38
42
|
]
|
39
43
|
|
40
44
|
m2 = MM::ListResponse.new(processes: another_process_array)
|
@@ -2,74 +2,21 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Invoker::Power::Balancer do
|
4
4
|
before do
|
5
|
-
@
|
5
|
+
@http_connection = mock("connection")
|
6
|
+
@balancer = Invoker::Power::Balancer.new(@http_connection, "http")
|
6
7
|
end
|
7
8
|
|
8
|
-
context "
|
9
|
-
it "should
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
matching_string = match[1]
|
14
|
-
expect(matching_string).to eq("foo")
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should match foo.dev:1080" do
|
18
|
-
match = @balancer.extract_host_from_domain("foo.dev:1080")
|
19
|
-
expect(match).to_not be_nil
|
20
|
-
|
21
|
-
matching_string = match[1]
|
22
|
-
expect(matching_string).to eq("foo")
|
9
|
+
context "when Host field is missing in the request" do
|
10
|
+
it "should return 400 as response when Host is missing" do
|
11
|
+
headers = {}
|
12
|
+
@http_connection.expects(:send_data).with() { |value| value =~ /400 Bad Request/i }
|
13
|
+
@balancer.headers_received(headers)
|
23
14
|
end
|
24
15
|
|
25
|
-
it "should
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
matching_string = match[1]
|
30
|
-
expect(matching_string).to eq("bar")
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should match hello-world.dev" do
|
34
|
-
match = @balancer.extract_host_from_domain("hello-world.dev")
|
35
|
-
expect(match).to_not be_nil
|
36
|
-
|
37
|
-
matching_string = match[1]
|
38
|
-
expect(matching_string).to eq("hello-world")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context "matching domain part of incoming request using xip.io" do
|
43
|
-
it "should do foo.10.0.0.1.xip.io match" do
|
44
|
-
match = @balancer.extract_host_from_domain("foo.10.0.0.1.xip.io")
|
45
|
-
expect(match).to_not be_nil
|
46
|
-
|
47
|
-
matching_string = match[1]
|
48
|
-
expect(matching_string).to eq("foo")
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should match foo.10.0.0.1.xip.io:1080" do
|
52
|
-
match = @balancer.extract_host_from_domain("foo.10.0.0.1.xip.io:1080")
|
53
|
-
expect(match).to_not be_nil
|
54
|
-
|
55
|
-
matching_string = match[1]
|
56
|
-
expect(matching_string).to eq("foo")
|
57
|
-
end
|
58
|
-
|
59
|
-
it "should match emacs.bar.10.0.0.1.xip.io" do
|
60
|
-
match = @balancer.extract_host_from_domain("emacs.bar.10.0.0.1.xip.io")
|
61
|
-
expect(match).to_not be_nil
|
62
|
-
|
63
|
-
matching_string = match[1]
|
64
|
-
expect(matching_string).to eq("bar")
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should match hello-world.10.0.0.1.xip.io" do
|
68
|
-
match = @balancer.extract_host_from_domain("hello-world.10.0.0.1.xip.io")
|
69
|
-
expect(match).to_not be_nil
|
70
|
-
|
71
|
-
matching_string = match[1]
|
72
|
-
expect(matching_string).to eq("hello-world")
|
16
|
+
it "should return 400 as response when Host is empty" do
|
17
|
+
headers = { 'Host' => '' }
|
18
|
+
@http_connection.expects(:send_data).with() { |value| value =~ /400 Bad Request/i }
|
19
|
+
@balancer.headers_received(headers)
|
73
20
|
end
|
74
21
|
end
|
75
22
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Invoker::Power::UrlRewriter do
|
4
|
+
let(:rewriter) { Invoker::Power::UrlRewriter.new }
|
5
|
+
|
6
|
+
context "matching domain part of incoming request" do
|
7
|
+
it "should do foo.dev match" do
|
8
|
+
match = rewriter.extract_host_from_domain("foo.dev")
|
9
|
+
expect(match).to_not be_empty
|
10
|
+
|
11
|
+
matching_string = match[0]
|
12
|
+
expect(matching_string).to eq("foo")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should match foo.dev:1080" do
|
16
|
+
match = rewriter.extract_host_from_domain("foo.dev:1080")
|
17
|
+
expect(match).to_not be_empty
|
18
|
+
|
19
|
+
matching_string = match[0]
|
20
|
+
expect(matching_string).to eq("foo")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should match emacs.bar.dev" do
|
24
|
+
match = rewriter.extract_host_from_domain("emacs.bar.dev")
|
25
|
+
expect(match).to_not be_empty
|
26
|
+
|
27
|
+
expect(match[0]).to eq("emacs.bar")
|
28
|
+
expect(match[1]).to eq("bar")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should match hello-world.dev" do
|
32
|
+
match = rewriter.extract_host_from_domain("hello-world.dev")
|
33
|
+
expect(match).to_not be_nil
|
34
|
+
|
35
|
+
expect(match[0]).to eq("hello-world")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: invoker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hemant Kumar
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-11-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
@@ -224,6 +224,7 @@ files:
|
|
224
224
|
- Rakefile
|
225
225
|
- TODO
|
226
226
|
- bin/invoker
|
227
|
+
- contrib/completion/invoker-completion.bash
|
227
228
|
- contrib/completion/invoker-completion.zsh
|
228
229
|
- invoker.gemspec
|
229
230
|
- lib/invoker.rb
|
@@ -269,12 +270,16 @@ files:
|
|
269
270
|
- lib/invoker/power/setup.rb
|
270
271
|
- lib/invoker/power/setup/distro/arch.rb
|
271
272
|
- lib/invoker/power/setup/distro/base.rb
|
273
|
+
- lib/invoker/power/setup/distro/debian.rb
|
274
|
+
- lib/invoker/power/setup/distro/mint.rb
|
272
275
|
- lib/invoker/power/setup/distro/redhat.rb
|
273
276
|
- lib/invoker/power/setup/distro/ubuntu.rb
|
274
277
|
- lib/invoker/power/setup/linux_setup.rb
|
275
278
|
- lib/invoker/power/setup/osx_setup.rb
|
279
|
+
- lib/invoker/power/templates/400.html
|
276
280
|
- lib/invoker/power/templates/404.html
|
277
281
|
- lib/invoker/power/templates/503.html
|
282
|
+
- lib/invoker/power/url_rewriter.rb
|
278
283
|
- lib/invoker/process_manager.rb
|
279
284
|
- lib/invoker/process_printer.rb
|
280
285
|
- lib/invoker/reactor.rb
|
@@ -304,6 +309,7 @@ files:
|
|
304
309
|
- spec/invoker/power/setup/linux_setup_spec.rb
|
305
310
|
- spec/invoker/power/setup/osx_setup_spec.rb
|
306
311
|
- spec/invoker/power/setup_spec.rb
|
312
|
+
- spec/invoker/power/url_rewriter_spec.rb
|
307
313
|
- spec/invoker/process_manager_spec.rb
|
308
314
|
- spec/invoker/reactor_spec.rb
|
309
315
|
- spec/spec_helper.rb
|
@@ -328,7 +334,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
328
334
|
version: '0'
|
329
335
|
requirements: []
|
330
336
|
rubyforge_project:
|
331
|
-
rubygems_version: 2.
|
337
|
+
rubygems_version: 2.4.5.1
|
332
338
|
signing_key:
|
333
339
|
specification_version: 4
|
334
340
|
summary: Something small for Process management
|
@@ -356,8 +362,8 @@ test_files:
|
|
356
362
|
- spec/invoker/power/setup/linux_setup_spec.rb
|
357
363
|
- spec/invoker/power/setup/osx_setup_spec.rb
|
358
364
|
- spec/invoker/power/setup_spec.rb
|
365
|
+
- spec/invoker/power/url_rewriter_spec.rb
|
359
366
|
- spec/invoker/process_manager_spec.rb
|
360
367
|
- spec/invoker/reactor_spec.rb
|
361
368
|
- spec/spec_helper.rb
|
362
369
|
- spec/support/mock_setup_file.rb
|
363
|
-
has_rdoc:
|