invoker 1.5.3 → 1.5.8

Sign up to get free protection for your applications and to get access to all the features.
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