invoker 1.4.1 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.rubocop.yml +0 -1
- data/.travis.yml +4 -2
- data/Dockerfile +7 -0
- data/Gemfile +3 -0
- data/Rakefile +8 -0
- data/examples/hello_sinatra.rb +26 -0
- data/examples/sample.ini +3 -0
- data/invoker.gemspec +2 -1
- data/lib/invoker.rb +20 -3
- data/lib/invoker/cli.rb +32 -6
- data/lib/invoker/dns_cache.rb +2 -2
- data/lib/invoker/ipc/add_http_command.rb +1 -1
- data/lib/invoker/ipc/dns_check_command.rb +2 -1
- data/lib/invoker/ipc/message.rb +2 -2
- data/lib/invoker/parsers/config.rb +4 -1
- data/lib/invoker/power/balancer.rb +16 -4
- data/lib/invoker/power/config.rb +3 -2
- data/lib/invoker/power/dns.rb +1 -1
- data/lib/invoker/power/pf_migrate.rb +1 -1
- data/lib/invoker/power/setup.rb +43 -4
- data/lib/invoker/power/setup/distro/arch.rb +1 -4
- data/lib/invoker/power/setup/distro/base.rb +23 -21
- data/lib/invoker/power/setup/distro/debian.rb +1 -1
- data/lib/invoker/power/setup/distro/opensuse.rb +11 -0
- data/lib/invoker/power/setup/distro/redhat.rb +1 -7
- 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 +46 -29
- data/lib/invoker/power/setup/osx_setup.rb +16 -28
- data/lib/invoker/power/url_rewriter.rb +6 -3
- data/lib/invoker/process_manager.rb +13 -7
- data/lib/invoker/version.rb +1 -1
- data/readme.md +4 -4
- data/spec/invoker/commander_spec.rb +19 -8
- data/spec/invoker/config_spec.rb +22 -27
- data/spec/invoker/invoker_spec.rb +2 -1
- data/spec/invoker/ipc/client_handler_spec.rb +11 -1
- data/spec/invoker/power/config_spec.rb +2 -1
- data/spec/invoker/power/pf_migrate_spec.rb +7 -0
- data/spec/invoker/power/setup/linux_setup_spec.rb +57 -9
- data/spec/invoker/power/setup/osx_setup_spec.rb +22 -8
- data/spec/invoker/power/url_rewriter_spec.rb +33 -1
- data/spec/invoker/power/web_sockets_spec.rb +61 -0
- data/spec/invoker/process_manager_spec.rb +34 -2
- data/spec/spec_helper.rb +12 -16
- metadata +27 -35
- data/spec/support/mock_setup_file.rb +0 -64
@@ -3,14 +3,11 @@ module Invoker
|
|
3
3
|
module Distro
|
4
4
|
class Arch < Base
|
5
5
|
def install_required_software
|
6
|
-
system("pacman -S --needed --noconfirm dnsmasq")
|
6
|
+
system("pacman -S --needed --noconfirm dnsmasq socat")
|
7
7
|
system("mkdir -p /etc/dnsmasq.d")
|
8
8
|
unless File.open("/etc/dnsmasq.conf").each_line.any? { |line| line.chomp == "conf-dir=/etc/dnsmasq.d" }
|
9
9
|
File.open("/etc/dnsmasq.conf", "a") {|f| f.write("conf-dir=/etc/dnsmasq.d") }
|
10
10
|
end
|
11
|
-
unless system("ls /usr/bin/rinetd > /dev/null 2>&1")
|
12
|
-
fail "You'll need to install rinetd from the AUR in order to continue"
|
13
|
-
end
|
14
11
|
end
|
15
12
|
end
|
16
13
|
end
|
@@ -2,37 +2,42 @@ module Invoker
|
|
2
2
|
module Power
|
3
3
|
module Distro
|
4
4
|
class Base
|
5
|
-
|
6
|
-
|
5
|
+
SOCAT_SHELLSCRIPT = "/usr/bin/invoker_forwarder.sh"
|
6
|
+
SOCAT_SYSTEMD = "/etc/systemd/system/socat_invoker.service"
|
7
|
+
RESOLVER_DIR = "/etc/dnsmasq.d"
|
8
|
+
attr_accessor :tld
|
7
9
|
|
8
|
-
def
|
10
|
+
def resolver_file
|
11
|
+
File.join(RESOLVER_DIR, "#{tld}-tld")
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.distro_installer(tld)
|
9
15
|
case Facter[:operatingsystem].value
|
10
16
|
when "Ubuntu"
|
11
17
|
require "invoker/power/setup/distro/ubuntu"
|
12
|
-
Ubuntu.new
|
18
|
+
Ubuntu.new(tld)
|
13
19
|
when "Fedora"
|
14
20
|
require "invoker/power/setup/distro/redhat"
|
15
|
-
Redhat.new
|
21
|
+
Redhat.new(tld)
|
16
22
|
when "Archlinux"
|
17
23
|
require "invoker/power/setup/distro/arch"
|
18
|
-
Arch.new
|
24
|
+
Arch.new(tld)
|
19
25
|
when "Debian"
|
20
26
|
require "invoker/power/setup/distro/debian"
|
21
|
-
Debian.new
|
27
|
+
Debian.new(tld)
|
22
28
|
when "LinuxMint"
|
23
29
|
require "invoker/power/setup/distro/mint"
|
24
|
-
Mint.new
|
30
|
+
Mint.new(tld)
|
31
|
+
when "OpenSuSE"
|
32
|
+
require "invoker/power/setup/distro/opensuse"
|
33
|
+
Opensuse.new(tld)
|
25
34
|
else
|
26
35
|
raise "Your selected distro is not supported by Invoker"
|
27
36
|
end
|
28
37
|
end
|
29
38
|
|
30
|
-
def
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
def rinetd_file
|
35
|
-
RINETD_FILE
|
39
|
+
def initialize(tld)
|
40
|
+
self.tld = tld
|
36
41
|
end
|
37
42
|
|
38
43
|
# Install required software
|
@@ -41,13 +46,10 @@ module Invoker
|
|
41
46
|
end
|
42
47
|
|
43
48
|
def restart_services
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
system("service rinetd restart")
|
49
|
-
system("service dnsmasq restart")
|
50
|
-
end
|
49
|
+
system("systemctl enable socat_invoker.service")
|
50
|
+
system("systemctl enable dnsmasq")
|
51
|
+
system("systemctl start socat_invoker.service")
|
52
|
+
system("systemctl restart dnsmasq")
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
@@ -3,13 +3,7 @@ module Invoker
|
|
3
3
|
module Distro
|
4
4
|
class Redhat < Base
|
5
5
|
def install_required_software
|
6
|
-
system("yum --assumeyes install dnsmasq
|
7
|
-
end
|
8
|
-
|
9
|
-
def restart_services
|
10
|
-
system("systemctl enable rinetd")
|
11
|
-
system("service rinetd restart")
|
12
|
-
system("service dnsmasq restart")
|
6
|
+
system("yum --assumeyes install dnsmasq socat")
|
13
7
|
end
|
14
8
|
end
|
15
9
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -e
|
3
|
+
KillJobs() {
|
4
|
+
for job in $(jobs -p); do
|
5
|
+
kill -s SIGTERM $job > /dev/null 2>&1 || (sleep 10 && kill -9 $job > /dev/null 2>&1 &)
|
6
|
+
done
|
7
|
+
}
|
8
|
+
|
9
|
+
# Whatever you need to clean here
|
10
|
+
trap KillJobs SIGINT SIGTERM EXIT
|
11
|
+
|
12
|
+
/usr/bin/socat TCP-LISTEN:80,reuseaddr,fork TCP:0.0.0.0:<%= http_port %>&
|
13
|
+
pid1=$!
|
14
|
+
/usr/bin/socat TCP-LISTEN:443,reuseaddr,fork TCP:0.0.0.0:<%= https_port %>&
|
15
|
+
pid2=$!
|
16
|
+
wait $pid1 $pid2
|
17
|
+
wait $pid1 $pid2
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require "invoker/power/setup/distro/base"
|
2
2
|
require "facter"
|
3
|
+
require 'erb'
|
4
|
+
require 'fileutils'
|
3
5
|
|
4
6
|
module Invoker
|
5
7
|
module Power
|
@@ -22,17 +24,27 @@ module Invoker
|
|
22
24
|
self
|
23
25
|
end
|
24
26
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
def uninstall_invoker
|
28
|
+
system("systemctl disable socat_invoker.service")
|
29
|
+
system("systemctl stop socat_invoker.service")
|
30
|
+
system("rm #{Invoker::Power::Distro::Base::SOCAT_SYSTEMD}")
|
31
|
+
system("rm #{Invoker::Power::Distro::Base::SOCAT_SHELLSCRIPT}")
|
32
|
+
initialize_distro_installer
|
33
|
+
remove_resolver_file
|
34
|
+
drop_to_normal_user
|
35
|
+
Invoker::Power::Config.delete
|
31
36
|
end
|
32
37
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
38
|
+
def resolver_file
|
39
|
+
distro_installer.resolver_file
|
40
|
+
end
|
41
|
+
|
42
|
+
def forwarder_script
|
43
|
+
File.join(File.dirname(__FILE__), "files/invoker_forwarder.sh.erb")
|
44
|
+
end
|
45
|
+
|
46
|
+
def socat_unit
|
47
|
+
File.join(File.dirname(__FILE__), "files/socat_invoker.service")
|
36
48
|
end
|
37
49
|
|
38
50
|
private
|
@@ -44,41 +56,46 @@ module Invoker
|
|
44
56
|
Facter::Util::Resolution.exec("[ -e /usr/bin/systemctl ] && echo 'true' || echo 'false'")
|
45
57
|
end
|
46
58
|
end
|
47
|
-
@distro_installer =
|
59
|
+
@distro_installer = Invoker::Power::Distro::Base.distro_installer(tld)
|
48
60
|
end
|
49
61
|
|
50
62
|
def install_resolver
|
51
|
-
File.open(
|
52
|
-
fl.write(
|
63
|
+
File.open(resolver_file, "w") do |fl|
|
64
|
+
fl.write(resolver_file_content)
|
53
65
|
end
|
54
66
|
end
|
55
67
|
|
56
68
|
def install_port_forwarder
|
57
|
-
|
58
|
-
|
59
|
-
fl << rinetd_setup(port_finder.http_port, port_finder.https_port)
|
60
|
-
end
|
69
|
+
install_forwarder_script(port_finder.http_port, port_finder.https_port)
|
70
|
+
install_systemd_unit
|
61
71
|
end
|
62
72
|
|
63
|
-
def
|
64
|
-
|
65
|
-
local
|
66
|
-
address
|
73
|
+
def resolver_file_content
|
74
|
+
content =<<-EOD
|
75
|
+
local=/#{tld}/
|
76
|
+
address=/#{tld}/127.0.0.1
|
67
77
|
EOD
|
68
|
-
|
78
|
+
content
|
69
79
|
end
|
70
80
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
81
|
+
def install_forwarder_script(http_port, https_port)
|
82
|
+
script_template = File.read(forwarder_script)
|
83
|
+
renderer = ERB.new(script_template)
|
84
|
+
script_output = renderer.result(binding)
|
85
|
+
File.open(Invoker::Power::Distro::Base::SOCAT_SHELLSCRIPT, "w") do |fl|
|
86
|
+
fl.write(script_output)
|
87
|
+
end
|
88
|
+
system("chmod +x #{Invoker::Power::Distro::Base::SOCAT_SHELLSCRIPT}")
|
89
|
+
end
|
90
|
+
|
91
|
+
def install_systemd_unit
|
92
|
+
FileUtils.cp(socat_unit, Invoker::Power::Distro::Base::SOCAT_SYSTEMD)
|
93
|
+
system("chmod 644 #{Invoker::Power::Distro::Base::SOCAT_SYSTEMD}")
|
77
94
|
end
|
78
95
|
|
79
96
|
def get_user_confirmation?
|
80
|
-
Invoker::Logger.puts("Invoker is going to install dnsmasq and
|
81
|
-
" It is also going to install a local resolver for
|
97
|
+
Invoker::Logger.puts("Invoker is going to install dnsmasq and socat on this machine."\
|
98
|
+
" It is also going to install a local resolver for .#{tld} domain and a socat service"\
|
82
99
|
" which will forward all local requests on port 80 and 443 to another port")
|
83
100
|
Invoker::Logger.puts("If you still want to proceed with installation, press y.")
|
84
101
|
Invoker::CLI::Question.agree("Proceed with installation (y/n) : ")
|
@@ -1,9 +1,12 @@
|
|
1
1
|
module Invoker
|
2
2
|
module Power
|
3
3
|
class OsxSetup < Setup
|
4
|
-
RESOLVER_FILE = "/etc/resolver/dev"
|
5
|
-
RESOLVER_DIR = "/etc/resolver"
|
6
4
|
FIREWALL_PLIST_FILE = "/Library/LaunchDaemons/com.codemancers.invoker.firewall.plist"
|
5
|
+
RESOLVER_DIR = "/etc/resolver"
|
6
|
+
|
7
|
+
def resolver_file
|
8
|
+
File.join(RESOLVER_DIR, tld)
|
9
|
+
end
|
7
10
|
|
8
11
|
def setup_invoker
|
9
12
|
if setup_resolver_file
|
@@ -30,33 +33,19 @@ module Invoker
|
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
http_port: port_finder.http_port,
|
38
|
-
https_port: port_finder.https_port
|
39
|
-
)
|
36
|
+
def build_power_config
|
37
|
+
config = super
|
38
|
+
config[:dns_port] = port_finder.dns_port
|
39
|
+
config
|
40
40
|
end
|
41
41
|
|
42
42
|
def install_resolver(dns_port)
|
43
|
-
open_resolver_for_write { |fl|
|
44
|
-
fl.write(resolve_string(dns_port))
|
45
|
-
}
|
43
|
+
open_resolver_for_write { |fl| fl.write(resolve_string(dns_port)) }
|
46
44
|
rescue Errno::EACCES
|
47
45
|
Invoker::Logger.puts("Running setup requires root access, please rerun it with sudo".color(:red))
|
48
46
|
raise
|
49
47
|
end
|
50
48
|
|
51
|
-
def remove_resolver_file
|
52
|
-
if File.exists?(RESOLVER_FILE)
|
53
|
-
File.delete(RESOLVER_FILE)
|
54
|
-
end
|
55
|
-
rescue Errno::EACCES
|
56
|
-
Invoker::Logger.puts("Running uninstall requires root access, please rerun it with sudo".color(:red))
|
57
|
-
raise
|
58
|
-
end
|
59
|
-
|
60
49
|
def install_firewall(http_port, https_port)
|
61
50
|
File.open(FIREWALL_PLIST_FILE, "w") { |fl|
|
62
51
|
fl.write(plist_string(http_port, https_port))
|
@@ -118,19 +107,18 @@ port #{dns_port}
|
|
118
107
|
end
|
119
108
|
|
120
109
|
def setup_resolver_file
|
121
|
-
return true unless File.
|
110
|
+
return true unless File.exist?(resolver_file)
|
111
|
+
|
122
112
|
Invoker::Logger.puts "Invoker has detected an existing Pow installation. We recommend "\
|
123
113
|
"that you uninstall pow and rerun this setup.".color(:red)
|
124
|
-
|
125
114
|
Invoker::Logger.puts "If you have already uninstalled Pow, proceed with installation"\
|
126
115
|
" by pressing y/n."
|
127
|
-
|
128
116
|
replace_resolver_flag = Invoker::CLI::Question.agree("Replace Pow configuration (y/n) : ")
|
129
117
|
|
130
118
|
if replace_resolver_flag
|
131
119
|
Invoker::Logger.puts "Invoker has overwritten one or more files created by Pow. "\
|
132
|
-
"If
|
133
|
-
" and turning it on. It
|
120
|
+
"If .#{tld} domains still don't resolve locally, try turning off the wi-fi"\
|
121
|
+
" and turning it on. It'll force OS X to reload network configuration".color(:green)
|
134
122
|
end
|
135
123
|
replace_resolver_flag
|
136
124
|
end
|
@@ -138,8 +126,8 @@ port #{dns_port}
|
|
138
126
|
private
|
139
127
|
|
140
128
|
def open_resolver_for_write
|
141
|
-
FileUtils.mkdir(RESOLVER_DIR) unless Dir.
|
142
|
-
fl = File.open(
|
129
|
+
FileUtils.mkdir(RESOLVER_DIR) unless Dir.exist?(RESOLVER_DIR)
|
130
|
+
fl = File.open(resolver_file, "w")
|
143
131
|
yield fl
|
144
132
|
ensure
|
145
133
|
fl && fl.close
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Invoker
|
2
2
|
module Power
|
3
3
|
class UrlRewriter
|
4
|
-
DEV_MATCH_REGEX = [/([\w.-]+)\.dev(\:\d+)?$/, /([\w-]+)\.dev(\:\d+)?$/]
|
5
|
-
|
6
4
|
def select_backend_config(complete_path)
|
7
5
|
possible_matches = extract_host_from_domain(complete_path)
|
8
6
|
exact_match = nil
|
@@ -17,7 +15,7 @@ module Invoker
|
|
17
15
|
|
18
16
|
def extract_host_from_domain(complete_path)
|
19
17
|
matching_strings = []
|
20
|
-
|
18
|
+
tld_match_regex.map do |regexp|
|
21
19
|
if (match_result = complete_path.match(regexp))
|
22
20
|
matching_strings << match_result[1]
|
23
21
|
end
|
@@ -27,6 +25,11 @@ module Invoker
|
|
27
25
|
|
28
26
|
private
|
29
27
|
|
28
|
+
def tld_match_regex
|
29
|
+
tld = Invoker.config.tld
|
30
|
+
[/([\w.-]+)\.#{tld}(\:\d+)?$/, /([\w-]+)\.#{tld}(\:\d+)?$/]
|
31
|
+
end
|
32
|
+
|
30
33
|
def dns_check(dns_args)
|
31
34
|
Invoker::IPC::UnixClient.send_command("dns_check", dns_args) do |dns_response|
|
32
35
|
dns_response
|
@@ -89,17 +89,23 @@ module Invoker
|
|
89
89
|
def load_env(directory = nil)
|
90
90
|
directory ||= ENV['PWD']
|
91
91
|
default_env = File.join(directory, '.env')
|
92
|
-
|
93
|
-
|
92
|
+
local_env = File.join(directory, '.env.local')
|
93
|
+
env = {}
|
94
|
+
|
95
|
+
if File.exist?(default_env)
|
96
|
+
env.merge!(Dotenv::Environment.new(default_env))
|
97
|
+
end
|
98
|
+
|
99
|
+
if File.exist?(local_env)
|
100
|
+
env.merge!(Dotenv::Environment.new(local_env))
|
101
|
+
end
|
102
|
+
|
103
|
+
env
|
94
104
|
end
|
95
105
|
|
96
106
|
def kill_workers
|
97
107
|
@workers.each do |key, worker|
|
98
|
-
|
99
|
-
Process.kill("INT", -Process.getpgid(worker.pid))
|
100
|
-
rescue Errno::ESRCH
|
101
|
-
Invoker::Logger.puts "Error killing #{key}"
|
102
|
-
end
|
108
|
+
kill_or_remove_process(worker.pid, "INT", worker.command_label)
|
103
109
|
end
|
104
110
|
@workers = {}
|
105
111
|
end
|
data/lib/invoker/version.rb
CHANGED
data/readme.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Invoker is a gem for managing processes in development environment.
|
2
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
7
|
|
8
8
|
## Usage ##
|
9
9
|
|
@@ -1,13 +1,22 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
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
|
+
|
4
13
|
describe "With no processes configured" do
|
5
|
-
before do
|
14
|
+
before(:each) do
|
6
15
|
@commander = Invoker::Commander.new
|
7
16
|
end
|
8
17
|
|
9
18
|
it "should throw error" do
|
10
|
-
|
19
|
+
Invoker.config.stubs(:processes).returns([])
|
11
20
|
|
12
21
|
expect {
|
13
22
|
@commander.start_manager
|
@@ -19,8 +28,9 @@ describe "Invoker::Commander" do
|
|
19
28
|
describe "when not daemonized" do
|
20
29
|
before do
|
21
30
|
processes = [OpenStruct.new(:label => "foobar", :cmd => "foobar_command", :dir => ENV['HOME'])]
|
22
|
-
|
23
|
-
|
31
|
+
Invoker.config.stubs(:processes).returns(processes)
|
32
|
+
Invoker.config.stubs(:autorunnable_processes).returns(processes)
|
33
|
+
Invoker.stubs(:can_run_balancer?).returns(false)
|
24
34
|
@commander = Invoker::Commander.new
|
25
35
|
Invoker.commander = @commander
|
26
36
|
end
|
@@ -52,8 +62,9 @@ describe "Invoker::Commander" do
|
|
52
62
|
describe "when daemonized" do
|
53
63
|
before do
|
54
64
|
processes = [OpenStruct.new(:label => "foobar", :cmd => "foobar_command", :dir => ENV['HOME'])]
|
55
|
-
|
56
|
-
|
65
|
+
Invoker.config.stubs(:processes).returns(processes)
|
66
|
+
Invoker.config.stubs(:autorunnable_processes).returns(processes)
|
67
|
+
Invoker.stubs(:can_run_balancer?).returns(false)
|
57
68
|
@commander = Invoker::Commander.new
|
58
69
|
Invoker.commander = @commander
|
59
70
|
Invoker.daemonize = true
|
@@ -94,8 +105,8 @@ describe "Invoker::Commander" do
|
|
94
105
|
OpenStruct.new(:label => "foobar", :cmd => "foobar_command", :dir => ENV['HOME']),
|
95
106
|
OpenStruct.new(:label => "panda", :cmd => "panda_command", :dir => ENV['HOME'], :disable_autorun => true)
|
96
107
|
]
|
97
|
-
|
98
|
-
|
108
|
+
Invoker.config.stubs(:processes).returns(@processes)
|
109
|
+
Invoker.config.stubs(:autorunnable_processes).returns([@processes.first])
|
99
110
|
|
100
111
|
@commander = Invoker::Commander.new
|
101
112
|
end
|