invoker 1.5.3 → 1.5.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/invoker.rb +5 -6
- data/lib/invoker/cli.rb +47 -14
- data/lib/invoker/command_worker.rb +6 -2
- data/lib/invoker/commander.rb +8 -2
- data/lib/invoker/ipc/unix_client.rb +2 -2
- data/lib/invoker/parsers/config.rb +3 -3
- data/lib/invoker/power/balancer.rb +6 -4
- data/lib/invoker/power/setup.rb +9 -6
- data/lib/invoker/power/setup/distro/base.rb +36 -13
- data/lib/invoker/power/setup/distro/ubuntu.rb +36 -0
- data/lib/invoker/power/setup/linux_setup.rb +11 -19
- data/lib/invoker/power/setup/osx_setup.rb +4 -4
- data/lib/invoker/process_manager.rb +7 -4
- data/lib/invoker/process_printer.rb +16 -0
- data/lib/invoker/reactor/reader.rb +17 -6
- data/lib/invoker/version.rb +1 -1
- data/spec/invoker/config_spec.rb +4 -4
- data/spec/invoker/power/balancer_spec.rb +31 -0
- data/spec/invoker/power/setup/linux_setup_spec.rb +97 -34
- data/spec/invoker/power/url_rewriter_spec.rb +24 -25
- data/spec/spec_helper.rb +3 -3
- metadata +56 -69
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -16
- data/.rspec +0 -2
- data/.rubocop.yml +0 -29
- data/.travis.yml +0 -10
- data/Dockerfile +0 -7
- data/Gemfile +0 -13
- data/MIT-LICENSE +0 -20
- data/Rakefile +0 -15
- data/TODO +0 -5
- data/contrib/completion/invoker-completion.bash +0 -70
- data/contrib/completion/invoker-completion.zsh +0 -62
- data/examples/hello_sinatra.rb +0 -26
- data/examples/sample.ini +0 -3
- data/invoker.gemspec +0 -43
- data/lib/invoker/power/pf_migrate.rb +0 -64
- data/lib/invoker/power/setup/distro/mint.rb +0 -10
- data/readme.md +0 -25
- data/spec/invoker/power/pf_migrate_spec.rb +0 -87
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b853190df0eac206efeac859446934d0e1b6df0fa93ad88d1ef950c2b9e30143
|
4
|
+
data.tar.gz: 127d6df5d280e555ed05b8b3449bfcc100ae6d9efb5bb447e01eaeedef16bef9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75ce1dd71098a4f5306797a8bc7ef82b7dafdbf21160a8633526fa697a4925b420d6f7ba8a3fcb230009fafa3d95e269bc384bffaa3dc7313996b689f2d00383
|
7
|
+
data.tar.gz: 3328f736e84fd2e681c59338c416b111c77199f0cdc01d06e2297ec5b82b3b9cc7b63d94bcaf77f6b68dd7c1be315936786e66014f135ad1be77fa68ef8631dd
|
data/lib/invoker.rb
CHANGED
@@ -6,8 +6,7 @@ require "formatador"
|
|
6
6
|
require "ostruct"
|
7
7
|
require "uuid"
|
8
8
|
require "json"
|
9
|
-
require "
|
10
|
-
require "rainbow/ext/string"
|
9
|
+
require "colorize"
|
11
10
|
require "etc"
|
12
11
|
|
13
12
|
require "invoker/version"
|
@@ -22,7 +21,6 @@ require "invoker/power/setup"
|
|
22
21
|
require "invoker/power/setup/linux_setup"
|
23
22
|
require "invoker/power/setup/osx_setup"
|
24
23
|
require "invoker/power/powerup"
|
25
|
-
require "invoker/power/pf_migrate"
|
26
24
|
require "invoker/errors"
|
27
25
|
require "invoker/parsers/procfile"
|
28
26
|
require "invoker/parsers/config"
|
@@ -36,9 +34,10 @@ require "invoker/process_printer"
|
|
36
34
|
module Invoker
|
37
35
|
class << self
|
38
36
|
attr_accessor :config, :tail_watchers, :commander
|
39
|
-
attr_accessor :dns_cache, :daemonize
|
37
|
+
attr_accessor :dns_cache, :daemonize, :nocolors, :certificate, :private_key
|
40
38
|
|
41
39
|
alias_method :daemonize?, :daemonize
|
40
|
+
alias_method :nocolors?, :nocolors
|
42
41
|
|
43
42
|
def darwin?
|
44
43
|
ruby_platform.downcase.include?("darwin")
|
@@ -73,7 +72,7 @@ module Invoker
|
|
73
72
|
return true if File.exist?(Invoker::Power::Config.config_file)
|
74
73
|
|
75
74
|
if throw_warning
|
76
|
-
Invoker::Logger.puts("Invoker has detected setup has not been run. Domain feature will not work without running setup command.".
|
75
|
+
Invoker::Logger.puts("Invoker has detected setup has not been run. Domain feature will not work without running setup command.".colorize(:red))
|
77
76
|
end
|
78
77
|
false
|
79
78
|
end
|
@@ -146,7 +145,7 @@ module Invoker
|
|
146
145
|
end
|
147
146
|
|
148
147
|
def default_tld
|
149
|
-
'
|
148
|
+
'test'
|
150
149
|
end
|
151
150
|
end
|
152
151
|
end
|
data/lib/invoker/cli.rb
CHANGED
@@ -19,6 +19,7 @@ module Invoker
|
|
19
19
|
def setup
|
20
20
|
Invoker::Power::Setup.install(get_tld(options))
|
21
21
|
end
|
22
|
+
map install: :setup
|
22
23
|
|
23
24
|
desc "version", "Print Invoker version"
|
24
25
|
def version
|
@@ -37,15 +38,27 @@ module Invoker
|
|
37
38
|
type: :boolean,
|
38
39
|
banner: "Daemonize the server into the background",
|
39
40
|
aliases: [:d]
|
41
|
+
option :nocolors,
|
42
|
+
type: :boolean,
|
43
|
+
banner: "Disable color in output",
|
44
|
+
aliases: [:nc]
|
45
|
+
option :certificate,
|
46
|
+
type: :string,
|
47
|
+
banner: "Path to certificate"
|
48
|
+
option :private_key,
|
49
|
+
type: :string,
|
50
|
+
banner: "Path to private key"
|
40
51
|
def start(file = nil)
|
41
52
|
Invoker.setup_config_location
|
42
53
|
port = options[:port] || 9000
|
43
54
|
Invoker.daemonize = options[:daemon]
|
55
|
+
Invoker.nocolors = options[:nocolors]
|
56
|
+
Invoker.certificate = options[:certificate]
|
57
|
+
Invoker.private_key = options[:private_key]
|
44
58
|
Invoker.load_invoker_config(file, port)
|
45
59
|
warn_about_notification
|
46
|
-
warn_about_old_configuration
|
47
60
|
pinger = Invoker::CLI::Pinger.new(unix_socket)
|
48
|
-
abort("Invoker is already running".
|
61
|
+
abort("Invoker is already running".colorize(:red)) if pinger.invoker_running?
|
49
62
|
Invoker.commander.start_manager
|
50
63
|
end
|
51
64
|
|
@@ -78,11 +91,35 @@ module Invoker
|
|
78
91
|
signal = options[:signal] || 'INT'
|
79
92
|
unix_socket.send_command('reload', process_name: name, signal: signal)
|
80
93
|
end
|
94
|
+
map restart: :reload
|
81
95
|
|
82
96
|
desc "list", "List all running processes"
|
97
|
+
option :raw,
|
98
|
+
type: :boolean,
|
99
|
+
banner: "Print process list in raw text format",
|
100
|
+
aliases: [:r]
|
101
|
+
option :wait,
|
102
|
+
type: :boolean,
|
103
|
+
banner: "wait for update",
|
104
|
+
aliases: [:w]
|
83
105
|
def list
|
84
|
-
|
85
|
-
|
106
|
+
if options[:wait]
|
107
|
+
Signal.trap("INT") { exit(0) }
|
108
|
+
loop do
|
109
|
+
puts "\e[H\e[2J"
|
110
|
+
unix_socket.send_command('list') do |response_object|
|
111
|
+
Invoker::ProcessPrinter.new(response_object).tap { |printer| printer.print_table }
|
112
|
+
end
|
113
|
+
sleep(5)
|
114
|
+
end
|
115
|
+
else
|
116
|
+
unix_socket.send_command('list') do |response_object|
|
117
|
+
if options[:raw]
|
118
|
+
Invoker::ProcessPrinter.new(response_object).tap { |printer| printer.print_raw_text }
|
119
|
+
else
|
120
|
+
Invoker::ProcessPrinter.new(response_object).tap { |printer| printer.print_table }
|
121
|
+
end
|
122
|
+
end
|
86
123
|
end
|
87
124
|
end
|
88
125
|
|
@@ -110,14 +147,16 @@ module Invoker
|
|
110
147
|
end
|
111
148
|
|
112
149
|
def self.valid_tasks
|
113
|
-
tasks.keys +
|
150
|
+
tasks.keys + %w(help install restart)
|
114
151
|
end
|
115
152
|
|
153
|
+
# TODO(kgrz): the default TLD option is duplicated in both this file and
|
154
|
+
# lib/invoker.rb May be assign this to a constant?
|
116
155
|
def get_tld(options)
|
117
156
|
if options[:tld] && !options[:tld].empty?
|
118
157
|
options[:tld]
|
119
158
|
else
|
120
|
-
'
|
159
|
+
'test'
|
121
160
|
end
|
122
161
|
end
|
123
162
|
|
@@ -137,7 +176,7 @@ module Invoker
|
|
137
176
|
require "libnotify"
|
138
177
|
rescue LoadError
|
139
178
|
Invoker::Logger.puts "You can install libnotify gem for Invoker notifications "\
|
140
|
-
"via system tray".
|
179
|
+
"via system tray".colorize(:red)
|
141
180
|
end
|
142
181
|
|
143
182
|
def warn_about_terminal_notifier
|
@@ -145,16 +184,10 @@ module Invoker
|
|
145
184
|
command_path = `which terminal-notifier`
|
146
185
|
if !command_path || command_path.empty?
|
147
186
|
Invoker::Logger.puts "You can enable OSX notification for processes "\
|
148
|
-
"by installing terminal-notifier gem".
|
187
|
+
"by installing terminal-notifier gem".colorize(:red)
|
149
188
|
end
|
150
189
|
end
|
151
190
|
end
|
152
|
-
|
153
|
-
def warn_about_old_configuration
|
154
|
-
Invoker::Power::PfMigrate.new.tap do |pf_migrator|
|
155
|
-
pf_migrator.migrate
|
156
|
-
end
|
157
|
-
end
|
158
191
|
end
|
159
192
|
end
|
160
193
|
|
@@ -25,9 +25,13 @@ module Invoker
|
|
25
25
|
# Print the lines received over the network
|
26
26
|
def receive_line(line)
|
27
27
|
tail_watchers = Invoker.tail_watchers[@command_label]
|
28
|
-
color_line = "#{@command_label.
|
28
|
+
color_line = "#{@command_label.colorize(color)} : #{line}"
|
29
29
|
plain_line = "#{@command_label} : #{line}"
|
30
|
-
Invoker
|
30
|
+
if Invoker.nocolors?
|
31
|
+
Invoker::Logger.puts plain_line
|
32
|
+
else
|
33
|
+
Invoker::Logger.puts color_line
|
34
|
+
end
|
31
35
|
if tail_watchers && !tail_watchers.empty?
|
32
36
|
json_encoded_tail_response = tail_response(color_line)
|
33
37
|
if json_encoded_tail_response
|
data/lib/invoker/commander.rb
CHANGED
@@ -82,10 +82,16 @@ module Invoker
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def install_interrupt_handler
|
85
|
-
Signal.trap("INT")
|
85
|
+
Signal.trap("INT") {
|
86
|
+
Invoker::Logger.puts("Stopping invoker")
|
86
87
|
process_manager.kill_workers
|
87
88
|
exit(0)
|
88
|
-
|
89
|
+
}
|
90
|
+
Signal.trap("TERM") {
|
91
|
+
Invoker::Logger.puts("Stopping invoker")
|
92
|
+
process_manager.kill_workers
|
93
|
+
exit(0)
|
94
|
+
}
|
89
95
|
end
|
90
96
|
|
91
97
|
def daemonize_app
|
@@ -28,7 +28,7 @@ module Invoker
|
|
28
28
|
begin
|
29
29
|
socket = Socket.unix(Invoker::IPC::Server::SOCKET_PATH)
|
30
30
|
rescue
|
31
|
-
abort("Invoker does not seem to be running".
|
31
|
+
abort("Invoker does not seem to be running".colorize(:red))
|
32
32
|
end
|
33
33
|
message_object = get_message_object(command, message)
|
34
34
|
send_json_message(socket, message_object)
|
@@ -49,7 +49,7 @@ module Invoker
|
|
49
49
|
def open_client_socket(abort_if_not_running = true)
|
50
50
|
Socket.unix(Invoker::IPC::Server::SOCKET_PATH) { |socket| yield socket }
|
51
51
|
rescue
|
52
|
-
abort_if_not_running && abort("Invoker does not seem to be running".
|
52
|
+
abort_if_not_running && abort("Invoker does not seem to be running".colorize(:red))
|
53
53
|
end
|
54
54
|
|
55
55
|
def send_json_message(socket, message_object)
|
@@ -90,7 +90,7 @@ module Invoker
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def print_message_and_abort
|
93
|
-
Invoker::Logger.puts("\n Invalid config file. Invoker requires an ini or a Procfile.".
|
93
|
+
Invoker::Logger.puts("\n Invalid config file. Invoker requires an ini or a Procfile.".colorize(:red))
|
94
94
|
abort
|
95
95
|
end
|
96
96
|
|
@@ -133,10 +133,10 @@ module Invoker
|
|
133
133
|
end
|
134
134
|
|
135
135
|
sleep_duration = section['sleep'].to_i
|
136
|
-
if sleep_duration
|
136
|
+
if sleep_duration >= 0
|
137
137
|
pconfig['sleep_duration'] = sleep_duration
|
138
138
|
else
|
139
|
-
pconfig['sleep_duration'] =
|
139
|
+
pconfig['sleep_duration'] = 0
|
140
140
|
end
|
141
141
|
|
142
142
|
OpenStruct.new(pconfig)
|
@@ -17,7 +17,7 @@ module Invoker
|
|
17
17
|
class InvokerHttpsProxy < InvokerHttpProxy
|
18
18
|
def post_init
|
19
19
|
super
|
20
|
-
start_tls
|
20
|
+
start_tls(private_key_file: Invoker.private_key, cert_chain_file: Invoker.certificate)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -65,12 +65,14 @@ module Invoker
|
|
65
65
|
return
|
66
66
|
end
|
67
67
|
@session = UUID.generate()
|
68
|
-
|
68
|
+
headers = headers.transform_keys(&:downcase)
|
69
|
+
|
70
|
+
if !headers['host'] || headers['host'].empty?
|
69
71
|
return_error_page(400)
|
70
72
|
return
|
71
73
|
end
|
72
74
|
|
73
|
-
dns_check_response = UrlRewriter.new.select_backend_config(headers['
|
75
|
+
dns_check_response = UrlRewriter.new.select_backend_config(headers['host'])
|
74
76
|
if dns_check_response && dns_check_response.port
|
75
77
|
connection.server(session, host: dns_check_response.ip, port: dns_check_response.port)
|
76
78
|
else
|
@@ -100,7 +102,7 @@ module Invoker
|
|
100
102
|
@backend_data = true
|
101
103
|
|
102
104
|
# check backend data for websockets connection. check for upgrade headers
|
103
|
-
# -
|
105
|
+
# - Upgrade: websocket\r\n
|
104
106
|
if data =~ /Upgrade: websocket/
|
105
107
|
@upgraded_to = "websocket"
|
106
108
|
end
|
data/lib/invoker/power/setup.rb
CHANGED
@@ -11,9 +11,11 @@ module Invoker
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.uninstall
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
if Invoker::Power::Config.has_config?
|
15
|
+
power_config = Invoker::Power::Config.load_config
|
16
|
+
selected_installer_klass = installer_klass
|
17
|
+
selected_installer_klass.new(power_config.tld).uninstall_invoker
|
18
|
+
end
|
17
19
|
end
|
18
20
|
|
19
21
|
def self.installer_klass
|
@@ -26,7 +28,7 @@ module Invoker
|
|
26
28
|
|
27
29
|
def initialize(tld)
|
28
30
|
if tld !~ /^[a-z]+$/
|
29
|
-
Invoker::Logger.puts("Please specify valid tld".
|
31
|
+
Invoker::Logger.puts("Please specify valid tld".colorize(:red))
|
30
32
|
exit(1)
|
31
33
|
end
|
32
34
|
self.tld = tld
|
@@ -36,7 +38,7 @@ module Invoker
|
|
36
38
|
if check_if_setup_can_run?
|
37
39
|
setup_invoker
|
38
40
|
else
|
39
|
-
Invoker::Logger.puts("The setup has been already run.".
|
41
|
+
Invoker::Logger.puts("The setup has been already run.".colorize(:red))
|
40
42
|
end
|
41
43
|
self
|
42
44
|
end
|
@@ -74,10 +76,11 @@ module Invoker
|
|
74
76
|
end
|
75
77
|
|
76
78
|
def remove_resolver_file
|
79
|
+
return if resolver_file.nil?
|
77
80
|
begin
|
78
81
|
safe_remove_file(resolver_file)
|
79
82
|
rescue Errno::EACCES
|
80
|
-
Invoker::Logger.puts("Running uninstall requires root access, please rerun it with sudo".
|
83
|
+
Invoker::Logger.puts("Running uninstall requires root access, please rerun it with sudo".colorize(:red))
|
81
84
|
raise
|
82
85
|
end
|
83
86
|
end
|
@@ -12,23 +12,19 @@ module Invoker
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.distro_installer(tld)
|
15
|
-
|
16
|
-
when "Ubuntu"
|
17
|
-
require "invoker/power/setup/distro/ubuntu"
|
18
|
-
Ubuntu.new(tld)
|
19
|
-
when "Fedora"
|
20
|
-
require "invoker/power/setup/distro/redhat"
|
21
|
-
Redhat.new(tld)
|
22
|
-
when "Archlinux"
|
15
|
+
if distro.start_with? "Arch Linux", "Manjaro Linux"
|
23
16
|
require "invoker/power/setup/distro/arch"
|
24
17
|
Arch.new(tld)
|
25
|
-
|
18
|
+
elsif distro.start_with? "Debian"
|
26
19
|
require "invoker/power/setup/distro/debian"
|
27
20
|
Debian.new(tld)
|
28
|
-
|
29
|
-
require "invoker/power/setup/distro/
|
30
|
-
|
31
|
-
|
21
|
+
elsif distro.start_with? "Fedora"
|
22
|
+
require "invoker/power/setup/distro/redhat"
|
23
|
+
Redhat.new(tld)
|
24
|
+
elsif distro.start_with? "Linux Mint", "Ubuntu"
|
25
|
+
require "invoker/power/setup/distro/ubuntu"
|
26
|
+
Ubuntu.new(tld)
|
27
|
+
elsif distro.start_with? "openSUSE"
|
32
28
|
require "invoker/power/setup/distro/opensuse"
|
33
29
|
Opensuse.new(tld)
|
34
30
|
else
|
@@ -36,6 +32,17 @@ module Invoker
|
|
36
32
|
end
|
37
33
|
end
|
38
34
|
|
35
|
+
def self.distro
|
36
|
+
@distro ||= if File.exist?('/etc/os-release')
|
37
|
+
File.read('/etc/os-release').each_line do |line|
|
38
|
+
parsed_line = line.chomp.tr('"', '').split('=')
|
39
|
+
break parsed_line[1] if parsed_line[0] == 'NAME'
|
40
|
+
end
|
41
|
+
else
|
42
|
+
raise "File /etc/os-release doesn't exist or not Linux"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
39
46
|
def initialize(tld)
|
40
47
|
self.tld = tld
|
41
48
|
end
|
@@ -51,6 +58,22 @@ module Invoker
|
|
51
58
|
system("systemctl start socat_invoker.service")
|
52
59
|
system("systemctl restart dnsmasq")
|
53
60
|
end
|
61
|
+
|
62
|
+
def install_packages
|
63
|
+
"dnsmasq and socat"
|
64
|
+
end
|
65
|
+
|
66
|
+
def install_other
|
67
|
+
" a local resolver for .#{tld} domain and"
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_user_confirmation?
|
71
|
+
Invoker::Logger.puts("Invoker is going to install #{install_packages} on this machine."\
|
72
|
+
" It is also going to install#{install_other} a socat service"\
|
73
|
+
" which will forward all local requests on port 80 and 443 to another port")
|
74
|
+
Invoker::Logger.puts("If you still want to proceed with installation, press y.")
|
75
|
+
Invoker::CLI::Question.agree("Proceed with installation (y/n) : ")
|
76
|
+
end
|
54
77
|
end
|
55
78
|
end
|
56
79
|
end
|
@@ -4,6 +4,42 @@ module Invoker
|
|
4
4
|
module Power
|
5
5
|
module Distro
|
6
6
|
class Ubuntu < Debian
|
7
|
+
def using_systemd_resolved?
|
8
|
+
return @_using_systemd_resolved if defined?(@_using_systemd_resolved)
|
9
|
+
@_using_systemd_resolved = system("systemctl is-active --quiet systemd-resolved")
|
10
|
+
end
|
11
|
+
|
12
|
+
def install_required_software
|
13
|
+
if using_systemd_resolved?
|
14
|
+
# Don't install dnsmasq if Ubuntu version uses systemd-resolved for DNS because they conflict
|
15
|
+
system("apt-get --assume-yes install socat")
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def install_packages
|
22
|
+
using_systemd_resolved? ? "socat" : super
|
23
|
+
end
|
24
|
+
|
25
|
+
def install_other
|
26
|
+
using_systemd_resolved? ? nil : super
|
27
|
+
end
|
28
|
+
|
29
|
+
def resolver_file
|
30
|
+
using_systemd_resolved? ? nil : super
|
31
|
+
end
|
32
|
+
|
33
|
+
def tld
|
34
|
+
using_systemd_resolved? ? 'localhost' : @tld
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_user_confirmation?
|
38
|
+
if using_systemd_resolved? && tld != 'localhost'
|
39
|
+
Invoker::Logger.puts("Ubuntu installations using systemd-resolved (typically Ubuntu 17+) only support the .localhost domain, so your tld setting (or the default) will be ignored.".colorize(:yellow))
|
40
|
+
end
|
41
|
+
super
|
42
|
+
end
|
7
43
|
end
|
8
44
|
end
|
9
45
|
end
|