invoker 1.5.3 → 1.5.8

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 (42) hide show
  1. checksums.yaml +5 -5
  2. data/lib/invoker.rb +5 -6
  3. data/lib/invoker/cli.rb +47 -14
  4. data/lib/invoker/command_worker.rb +6 -2
  5. data/lib/invoker/commander.rb +8 -2
  6. data/lib/invoker/ipc/unix_client.rb +2 -2
  7. data/lib/invoker/parsers/config.rb +3 -3
  8. data/lib/invoker/power/balancer.rb +6 -4
  9. data/lib/invoker/power/setup.rb +9 -6
  10. data/lib/invoker/power/setup/distro/base.rb +36 -13
  11. data/lib/invoker/power/setup/distro/ubuntu.rb +36 -0
  12. data/lib/invoker/power/setup/linux_setup.rb +11 -19
  13. data/lib/invoker/power/setup/osx_setup.rb +4 -4
  14. data/lib/invoker/process_manager.rb +7 -4
  15. data/lib/invoker/process_printer.rb +16 -0
  16. data/lib/invoker/reactor/reader.rb +17 -6
  17. data/lib/invoker/version.rb +1 -1
  18. data/spec/invoker/config_spec.rb +4 -4
  19. data/spec/invoker/power/balancer_spec.rb +31 -0
  20. data/spec/invoker/power/setup/linux_setup_spec.rb +97 -34
  21. data/spec/invoker/power/url_rewriter_spec.rb +24 -25
  22. data/spec/spec_helper.rb +3 -3
  23. metadata +56 -69
  24. data/.coveralls.yml +0 -1
  25. data/.gitignore +0 -16
  26. data/.rspec +0 -2
  27. data/.rubocop.yml +0 -29
  28. data/.travis.yml +0 -10
  29. data/Dockerfile +0 -7
  30. data/Gemfile +0 -13
  31. data/MIT-LICENSE +0 -20
  32. data/Rakefile +0 -15
  33. data/TODO +0 -5
  34. data/contrib/completion/invoker-completion.bash +0 -70
  35. data/contrib/completion/invoker-completion.zsh +0 -62
  36. data/examples/hello_sinatra.rb +0 -26
  37. data/examples/sample.ini +0 -3
  38. data/invoker.gemspec +0 -43
  39. data/lib/invoker/power/pf_migrate.rb +0 -64
  40. data/lib/invoker/power/setup/distro/mint.rb +0 -10
  41. data/readme.md +0 -25
  42. data/spec/invoker/power/pf_migrate_spec.rb +0 -87
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e1da2ee349b145013878352cca28cc1de9ed13c5
4
- data.tar.gz: 066597992a678fa848f9d6d9e36798272141ff7b
2
+ SHA256:
3
+ metadata.gz: b853190df0eac206efeac859446934d0e1b6df0fa93ad88d1ef950c2b9e30143
4
+ data.tar.gz: 127d6df5d280e555ed05b8b3449bfcc100ae6d9efb5bb447e01eaeedef16bef9
5
5
  SHA512:
6
- metadata.gz: 51bd2c4294e3d7b97dfe909f1289b4d62b170db3171c4cee96c1d0848df98d0ab286835f7d8de9a321c2da3e4695aea3e1010a25b308228071f981c2f4dc51ad
7
- data.tar.gz: e265b1e4452c688517aa5a648a5fd81fc34c3a6a395061e7c486723318d6031018778fe3adcf76219dc8771c0b4f73168491ef86b4229d63b3fd8d26d3058f82
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 "rainbow"
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.".color(:red))
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
- 'dev'
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".color(:red)) if pinger.invoker_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
- unix_socket.send_command('list') do |response_object|
85
- Invoker::ProcessPrinter.new(response_object).tap { |printer| printer.print_table }
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 + ["help"]
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
- 'dev'
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".color(:red)
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".color(:red)
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.color(color)} : #{line}"
28
+ color_line = "#{@command_label.colorize(color)} : #{line}"
29
29
  plain_line = "#{@command_label} : #{line}"
30
- Invoker::Logger.puts plain_line
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
@@ -82,10 +82,16 @@ module Invoker
82
82
  end
83
83
 
84
84
  def install_interrupt_handler
85
- Signal.trap("INT") do
85
+ Signal.trap("INT") {
86
+ Invoker::Logger.puts("Stopping invoker")
86
87
  process_manager.kill_workers
87
88
  exit(0)
88
- end
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".color(:red))
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".color(:red))
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.".color(:red))
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 > 0
136
+ if sleep_duration >= 0
137
137
  pconfig['sleep_duration'] = sleep_duration
138
138
  else
139
- pconfig['sleep_duration'] = 1
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
- if !headers['Host'] || headers['Host'].empty?
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['Host'])
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
- # - Upgarde: websocket\r\n
105
+ # - Upgrade: websocket\r\n
104
106
  if data =~ /Upgrade: websocket/
105
107
  @upgraded_to = "websocket"
106
108
  end
@@ -11,9 +11,11 @@ module Invoker
11
11
  end
12
12
 
13
13
  def self.uninstall
14
- power_config = Invoker::Power::Config.load_config
15
- selected_installer_klass = installer_klass
16
- selected_installer_klass.new(power_config.tld).uninstall_invoker
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".color(:red))
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.".color(:red))
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".color(:red))
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
- case Facter[:operatingsystem].value
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
- when "Debian"
18
+ elsif distro.start_with? "Debian"
26
19
  require "invoker/power/setup/distro/debian"
27
20
  Debian.new(tld)
28
- when "LinuxMint"
29
- require "invoker/power/setup/distro/mint"
30
- Mint.new(tld)
31
- when "OpenSuSE"
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