invoker_ruby34 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/bin/invoker +7 -0
  3. data/lib/invoker/cli/pinger.rb +23 -0
  4. data/lib/invoker/cli/question.rb +15 -0
  5. data/lib/invoker/cli/tail.rb +34 -0
  6. data/lib/invoker/cli/tail_watcher.rb +34 -0
  7. data/lib/invoker/cli.rb +197 -0
  8. data/lib/invoker/command_worker.rb +64 -0
  9. data/lib/invoker/commander.rb +101 -0
  10. data/lib/invoker/daemon.rb +126 -0
  11. data/lib/invoker/dns_cache.rb +23 -0
  12. data/lib/invoker/errors.rb +17 -0
  13. data/lib/invoker/event/manager.rb +79 -0
  14. data/lib/invoker/ipc/add_command.rb +12 -0
  15. data/lib/invoker/ipc/add_http_command.rb +10 -0
  16. data/lib/invoker/ipc/base_command.rb +24 -0
  17. data/lib/invoker/ipc/client_handler.rb +26 -0
  18. data/lib/invoker/ipc/dns_check_command.rb +17 -0
  19. data/lib/invoker/ipc/list_command.rb +11 -0
  20. data/lib/invoker/ipc/message/list_response.rb +35 -0
  21. data/lib/invoker/ipc/message/tail_response.rb +10 -0
  22. data/lib/invoker/ipc/message.rb +170 -0
  23. data/lib/invoker/ipc/ping_command.rb +10 -0
  24. data/lib/invoker/ipc/reload_command.rb +12 -0
  25. data/lib/invoker/ipc/remove_command.rb +12 -0
  26. data/lib/invoker/ipc/server.rb +26 -0
  27. data/lib/invoker/ipc/tail_command.rb +11 -0
  28. data/lib/invoker/ipc/unix_client.rb +60 -0
  29. data/lib/invoker/ipc.rb +45 -0
  30. data/lib/invoker/logger.rb +13 -0
  31. data/lib/invoker/parsers/config.rb +184 -0
  32. data/lib/invoker/parsers/procfile.rb +86 -0
  33. data/lib/invoker/power/balancer.rb +133 -0
  34. data/lib/invoker/power/config.rb +77 -0
  35. data/lib/invoker/power/dns.rb +38 -0
  36. data/lib/invoker/power/http_parser.rb +68 -0
  37. data/lib/invoker/power/http_response.rb +81 -0
  38. data/lib/invoker/power/port_finder.rb +49 -0
  39. data/lib/invoker/power/power.rb +3 -0
  40. data/lib/invoker/power/powerup.rb +29 -0
  41. data/lib/invoker/power/setup/distro/arch.rb +15 -0
  42. data/lib/invoker/power/setup/distro/base.rb +80 -0
  43. data/lib/invoker/power/setup/distro/debian.rb +11 -0
  44. data/lib/invoker/power/setup/distro/opensuse.rb +11 -0
  45. data/lib/invoker/power/setup/distro/redhat.rb +11 -0
  46. data/lib/invoker/power/setup/distro/ubuntu.rb +46 -0
  47. data/lib/invoker/power/setup/files/invoker_forwarder.sh.erb +17 -0
  48. data/lib/invoker/power/setup/files/socat_invoker.service +12 -0
  49. data/lib/invoker/power/setup/linux_setup.rb +97 -0
  50. data/lib/invoker/power/setup/osx_setup.rb +137 -0
  51. data/lib/invoker/power/setup.rb +93 -0
  52. data/lib/invoker/power/templates/400.html +40 -0
  53. data/lib/invoker/power/templates/404.html +40 -0
  54. data/lib/invoker/power/templates/503.html +40 -0
  55. data/lib/invoker/power/url_rewriter.rb +40 -0
  56. data/lib/invoker/process_manager.rb +201 -0
  57. data/lib/invoker/process_printer.rb +59 -0
  58. data/lib/invoker/reactor/reader.rb +65 -0
  59. data/lib/invoker/reactor.rb +37 -0
  60. data/lib/invoker/version.rb +47 -0
  61. data/lib/invoker.rb +151 -0
  62. data/spec/invoker/cli/pinger_spec.rb +22 -0
  63. data/spec/invoker/cli/tail_watcher_spec.rb +39 -0
  64. data/spec/invoker/cli_spec.rb +27 -0
  65. data/spec/invoker/command_worker_spec.rb +45 -0
  66. data/spec/invoker/commander_spec.rb +152 -0
  67. data/spec/invoker/config_spec.rb +361 -0
  68. data/spec/invoker/daemon_spec.rb +34 -0
  69. data/spec/invoker/event/manager_spec.rb +67 -0
  70. data/spec/invoker/invoker_spec.rb +71 -0
  71. data/spec/invoker/ipc/client_handler_spec.rb +54 -0
  72. data/spec/invoker/ipc/dns_check_command_spec.rb +32 -0
  73. data/spec/invoker/ipc/message/list_response_spec.rb +24 -0
  74. data/spec/invoker/ipc/message_spec.rb +49 -0
  75. data/spec/invoker/ipc/unix_client_spec.rb +29 -0
  76. data/spec/invoker/power/balancer_spec.rb +53 -0
  77. data/spec/invoker/power/config_spec.rb +18 -0
  78. data/spec/invoker/power/http_parser_spec.rb +32 -0
  79. data/spec/invoker/power/http_response_spec.rb +34 -0
  80. data/spec/invoker/power/port_finder_spec.rb +16 -0
  81. data/spec/invoker/power/setup/linux_setup_spec.rb +166 -0
  82. data/spec/invoker/power/setup/osx_setup_spec.rb +105 -0
  83. data/spec/invoker/power/setup_spec.rb +4 -0
  84. data/spec/invoker/power/url_rewriter_spec.rb +69 -0
  85. data/spec/invoker/power/web_sockets_spec.rb +61 -0
  86. data/spec/invoker/process_manager_spec.rb +130 -0
  87. data/spec/invoker/reactor_spec.rb +6 -0
  88. data/spec/spec_helper.rb +43 -0
  89. metadata +374 -0
@@ -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>Application not found</h1>
36
+ <hr>
37
+ <h2>Invoker could not find the application. Please check the configuration file.<h2>
38
+ </div>
39
+ </body>
40
+ </html>
@@ -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>Application not running</h1>
36
+ <hr>
37
+ <h2>Invoker did not get any response. Please check if the application is running.<h2>
38
+ </div>
39
+ </body>
40
+ </html>
@@ -0,0 +1,40 @@
1
+ module Invoker
2
+ module Power
3
+ class UrlRewriter
4
+ def select_backend_config(complete_path)
5
+ possible_matches = extract_host_from_domain(complete_path)
6
+ exact_match = nil
7
+ possible_matches.each do |match|
8
+ if match
9
+ exact_match = dns_check(process_name: match)
10
+ break if exact_match.port
11
+ end
12
+ end
13
+ exact_match
14
+ end
15
+
16
+ def extract_host_from_domain(complete_path)
17
+ matching_strings = []
18
+ tld_match_regex.map do |regexp|
19
+ if (match_result = complete_path.match(regexp))
20
+ matching_strings << match_result[1]
21
+ end
22
+ end
23
+ matching_strings.uniq
24
+ end
25
+
26
+ private
27
+
28
+ def tld_match_regex
29
+ tld = Invoker.config.tld
30
+ [/([\w.-]+)\.#{tld}(\:\d+)?$/, /([\w-]+)\.#{tld}(\:\d+)?$/]
31
+ end
32
+
33
+ def dns_check(dns_args)
34
+ Invoker::IPC::UnixClient.send_command("dns_check", dns_args) do |dns_response|
35
+ dns_response
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,201 @@
1
+ module Invoker
2
+ # Class is responsible for managing all the processes Invoker is supposed
3
+ # to manage. Takes care of starting, stopping and restarting processes.
4
+ class ProcessManager
5
+ LABEL_COLORS = [:green, :yellow, :blue, :magenta, :cyan]
6
+ attr_accessor :open_pipes, :workers
7
+
8
+ def initialize
9
+ @open_pipes = {}
10
+ @workers = {}
11
+ @worker_mutex = Mutex.new
12
+ @thread_group = ThreadGroup.new
13
+ end
14
+
15
+ def start_process(process_info)
16
+ m, s = PTY.open
17
+ s.raw! # disable newline conversion.
18
+
19
+ pid = run_command(process_info, s)
20
+
21
+ s.close
22
+
23
+ worker = CommandWorker.new(process_info.label, m, pid, select_color)
24
+
25
+ add_worker(worker)
26
+ wait_on_pid(process_info.label, pid)
27
+ end
28
+
29
+ # Start a process given their name
30
+ # @param process_name [String] Command label of process specified in config file.
31
+ def start_process_by_name(process_name)
32
+ if process_running?(process_name)
33
+ Invoker::Logger.puts "\nProcess '#{process_name}' is already running".colorize(:red)
34
+ return false
35
+ end
36
+
37
+ process_info = Invoker.config.process(process_name)
38
+ start_process(process_info) if process_info
39
+ end
40
+
41
+ # Remove a process from list of processes managed by invoker supervisor.It also
42
+ # kills the process before removing it from the list.
43
+ #
44
+ # @param remove_message [Invoker::IPC::Message::Remove]
45
+ # @return [Boolean] if process existed and was removed else false
46
+ def stop_process(remove_message)
47
+ worker = workers[remove_message.process_name]
48
+ command_label = remove_message.process_name
49
+ return false unless worker
50
+ signal_to_use = remove_message.signal || 'INT'
51
+
52
+ Invoker::Logger.puts("Removing #{command_label} with signal #{signal_to_use}".colorize(:red))
53
+ kill_or_remove_process(worker.pid, signal_to_use, command_label)
54
+ end
55
+
56
+ # Receive a message from user to restart a Process
57
+ # @param [Invoker::IPC::Message::Reload]
58
+ def restart_process(reload_message)
59
+ command_label = reload_message.process_name
60
+ if stop_process(reload_message.remove_message)
61
+ Invoker.commander.schedule_event(command_label, :worker_removed) do
62
+ start_process_by_name(command_label)
63
+ end
64
+ else
65
+ start_process_by_name(command_label)
66
+ end
67
+ end
68
+
69
+ def run_power_server
70
+ return unless Invoker.can_run_balancer?(false)
71
+
72
+ powerup_id = Invoker::Power::Powerup.fork_and_start
73
+ wait_on_pid("powerup_manager", powerup_id)
74
+ at_exit do
75
+ begin
76
+ Process.kill("INT", powerup_id)
77
+ rescue Errno::ESRCH; end
78
+ end
79
+ end
80
+
81
+ # Given a file descriptor returns the worker object
82
+ #
83
+ # @param fd [IO] an IO object with valid file descriptor
84
+ # @return [Invoker::CommandWorker] The worker object which is associated with this fd
85
+ def get_worker_from_fd(fd)
86
+ open_pipes[fd.fileno]
87
+ end
88
+
89
+ def load_env(directory = nil)
90
+ directory ||= ENV['PWD']
91
+
92
+ if !directory || directory.empty? || !Dir.exist?(directory)
93
+ return {}
94
+ end
95
+
96
+ default_env = File.join(directory, '.env')
97
+ local_env = File.join(directory, '.env.local')
98
+ env = {}
99
+
100
+ if File.exist?(default_env)
101
+ env.merge!(Dotenv::Environment.new(default_env))
102
+ end
103
+
104
+ if File.exist?(local_env)
105
+ env.merge!(Dotenv::Environment.new(local_env))
106
+ end
107
+
108
+ env
109
+ end
110
+
111
+ def kill_workers
112
+ @workers.each do |key, worker|
113
+ kill_or_remove_process(worker.pid, "INT", worker.command_label)
114
+ end
115
+ @workers = {}
116
+ end
117
+
118
+ # List currently running commands
119
+ def process_list
120
+ Invoker::IPC::Message::ListResponse.from_workers(workers)
121
+ end
122
+
123
+ private
124
+
125
+ def wait_on_pid(command_label, pid)
126
+ raise Invoker::Errors::ToomanyOpenConnections if @thread_group.enclosed?
127
+
128
+ thread = Thread.new do
129
+ Process.wait(pid)
130
+ message = "Process with command #{command_label} exited with status #{$?.exitstatus}"
131
+ Invoker::Logger.puts("\n#{message}".colorize(:red))
132
+ Invoker.notify_user(message)
133
+ Invoker.commander.trigger(command_label, :exit)
134
+ end
135
+ @thread_group.add(thread)
136
+ end
137
+
138
+ def select_color
139
+ selected_color = LABEL_COLORS.shift
140
+ LABEL_COLORS.push(selected_color)
141
+ selected_color
142
+ end
143
+
144
+ def process_running?(command_label)
145
+ !!workers[command_label]
146
+ end
147
+
148
+ def kill_or_remove_process(pid, signal_to_use, command_label)
149
+ process_kill(pid, signal_to_use)
150
+ true
151
+ rescue Errno::ESRCH
152
+ Invoker::Logger.puts("Killing process with #{pid} and name #{command_label} failed".colorize(:red))
153
+ remove_worker(command_label, false)
154
+ false
155
+ end
156
+
157
+ def process_kill(pid, signal_to_use)
158
+ if signal_to_use.to_i == 0
159
+ Process.kill(signal_to_use, -Process.getpgid(pid))
160
+ else
161
+ Process.kill(signal_to_use.to_i, -Process.getpgid(pid))
162
+ end
163
+ end
164
+
165
+ # Remove worker from all collections
166
+ def remove_worker(command_label, trigger_event = true)
167
+ worker = @workers[command_label]
168
+ if worker
169
+ @open_pipes.delete(worker.pipe_end.fileno)
170
+ @workers.delete(command_label)
171
+ # Move label color to front of array so it's reused first
172
+ LABEL_COLORS.delete(worker.color)
173
+ LABEL_COLORS.unshift(worker.color)
174
+ end
175
+ if trigger_event
176
+ Invoker.commander.trigger(command_label, :worker_removed)
177
+ end
178
+ end
179
+
180
+ # add worker to global collections
181
+ def add_worker(worker)
182
+ @open_pipes[worker.pipe_end.fileno] = worker
183
+ @workers[worker.command_label] = worker
184
+ Invoker.commander.watch_for_read(worker.pipe_end)
185
+ end
186
+
187
+ def run_command(process_info, write_pipe)
188
+ command_label = process_info.label
189
+
190
+ Invoker.commander.schedule_event(command_label, :exit) { remove_worker(command_label) }
191
+
192
+ env_options = load_env(process_info.dir)
193
+
194
+ spawn_options = {
195
+ :chdir => process_info.dir || ENV['PWD'], :out => write_pipe, :err => write_pipe,
196
+ :pgroup => true, :close_others => true, :in => :close
197
+ }
198
+ Invoker.run_without_bundler { spawn(env_options, process_info.cmd, spawn_options) }
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,59 @@
1
+ module Invoker
2
+ class ProcessPrinter
3
+ MAX_COLUMN_WIDTH = 40
4
+ attr_accessor :list_response
5
+
6
+ def initialize(list_response)
7
+ self.list_response = list_response
8
+ end
9
+
10
+ def print_table
11
+ hash_with_colors = []
12
+ list_response.processes.each do |process|
13
+ if process.pid
14
+ hash_with_colors << colorize_hash(process, "green")
15
+ else
16
+ hash_with_colors << colorize_hash(process, "light_black")
17
+ end
18
+ end
19
+ Formatador.display_compact_table(hash_with_colors)
20
+ end
21
+
22
+ def print_raw_text
23
+ list_response.processes.each do |process|
24
+ Formatador.display_line("[bold]Process Name : #{process.process_name}[/]")
25
+ Formatador.indent {
26
+ Formatador.display_line("Dir : #{process.dir}")
27
+ if process.pid
28
+ Formatador.display_line("PID : #{process.pid}")
29
+ else
30
+ Formatador.display_line("PID : Not Running")
31
+ end
32
+ Formatador.display_line("Port : #{process.port}")
33
+ Formatador.display_line("Command : #{process.shell_command}")
34
+ }
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def colorize_hash(process, color)
41
+ hash_with_colors = {}
42
+
43
+ hash_with_colors['dir'] = colored_string(process.dir, color)
44
+ hash_with_colors['pid'] = colored_string(process.pid || 'Not Running', color)
45
+ hash_with_colors['port'] = colored_string(process.port, color)
46
+ hash_with_colors['shell_command'] = colored_string(process.shell_command, color)
47
+ hash_with_colors['process_name'] = colored_string(process.process_name, color)
48
+ hash_with_colors
49
+ end
50
+
51
+ def colored_string(string, color)
52
+ string = string.to_s
53
+ if string.length > MAX_COLUMN_WIDTH
54
+ string = "#{string[0..MAX_COLUMN_WIDTH]}.."
55
+ end
56
+ "[#{color}]#{string}[/]"
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,65 @@
1
+ module Invoker
2
+ class Reactor::Reader
3
+ attr_accessor :read_array
4
+
5
+ def initialize
6
+ @read_array = []
7
+ end
8
+
9
+ def watch_for_read(socket)
10
+ @read_array << socket
11
+ end
12
+
13
+ def handle_read_event(read_ready_fds)
14
+ ready_fds = read_ready_fds.flatten.compact
15
+ ready_fds.each { |ready_fd| process_read(ready_fd) }
16
+ end
17
+
18
+ private
19
+
20
+ def process_read(ready_fd)
21
+ command_worker = Invoker.commander.get_worker_from_fd(ready_fd)
22
+ begin
23
+ data = read_data(ready_fd)
24
+ send_data_to_worker(data, command_worker)
25
+ rescue Invoker::Errors::ProcessTerminated
26
+ remove_from_read_monitoring(command_worker, ready_fd)
27
+ end
28
+ end
29
+
30
+ def send_data_to_worker(data, command_worker)
31
+ if command_worker
32
+ command_worker.receive_data(data)
33
+ else
34
+ Invoker::Logger.puts("No reader found for incoming data")
35
+ end
36
+ end
37
+
38
+ def remove_from_read_monitoring(command_worker, ready_fd)
39
+ if command_worker
40
+ read_array.delete(command_worker.pipe_end)
41
+ command_worker.unbind
42
+ else
43
+ read_array.delete(ready_fd)
44
+ end
45
+ rescue StandardError => error
46
+ Invoker::Logger.puts(error.message)
47
+ Invoker::Logger.puts(error.backtrace)
48
+ end
49
+
50
+ def read_data(ready_fd)
51
+ sock_data = []
52
+ begin
53
+ while(t_data = ready_fd.read_nonblock(64))
54
+ sock_data << t_data
55
+ end
56
+ rescue Errno::EAGAIN
57
+ return sock_data.join
58
+ rescue Errno::EWOULDBLOCK
59
+ return sock_data.join
60
+ rescue
61
+ raise Invoker::Errors::ProcessTerminated.new(ready_fd,sock_data.join)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,37 @@
1
+ module Invoker
2
+ class Reactor
3
+ attr_accessor :reader
4
+
5
+ def initialize
6
+ @reader = Invoker::Reactor::Reader.new
7
+ end
8
+
9
+ def watch_for_read(fd)
10
+ reader.watch_for_read(fd)
11
+ end
12
+
13
+ # Writes data to client socket and raises error if errors
14
+ # while writing
15
+ def send_data(socket, data)
16
+ socket.write(data)
17
+ rescue
18
+ raise Invoker::Errors::ClientDisconnected
19
+ end
20
+
21
+ def monitor_for_fd_events
22
+ ready_read_fds, _ , _ = select(*options_for_select)
23
+
24
+ if ready_read_fds && !ready_read_fds.empty?
25
+ reader.handle_read_event(ready_read_fds)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def options_for_select
32
+ [reader.read_array, [], [], 0.05]
33
+ end
34
+ end
35
+ end
36
+
37
+ require "invoker/reactor/reader"
@@ -0,0 +1,47 @@
1
+ module Invoker
2
+ class Version
3
+ include Comparable
4
+ attr_reader :major, :minor, :patch
5
+
6
+ def initialize(number)
7
+ t_major, t_minor, t_patch = number.split('.')
8
+ @major = t_major.to_i
9
+ @minor = t_minor.to_i
10
+ @patch = t_patch.to_i
11
+ end
12
+
13
+ def to_a
14
+ [major, minor, patch].compact
15
+ end
16
+
17
+ def <=>(version)
18
+ (major.to_i <=> version.major.to_i).nonzero? ||
19
+ (minor.to_i <=> version.minor.to_i).nonzero? ||
20
+ patch.to_i <=> version.patch.to_i
21
+ end
22
+
23
+ def matches?(operator, number)
24
+ version = Version.new(number)
25
+ self == version
26
+
27
+ return self == version if operator == '='
28
+ return self > version if operator == '>'
29
+ return self < version if operator == '<'
30
+ return version <= self && version.next > self if operator == '~>'
31
+ end
32
+
33
+ def next
34
+ next_splits = to_a
35
+
36
+ if next_splits.length == 1
37
+ next_splits[0] += 1
38
+ else
39
+ next_splits[-2] += 1
40
+ next_splits[-1] = 0
41
+ end
42
+
43
+ Version.new(next_splits.join('.'))
44
+ end
45
+ end
46
+ VERSION = "2.0.0"
47
+ end
data/lib/invoker.rb ADDED
@@ -0,0 +1,151 @@
1
+ $: << File.dirname(__FILE__) unless $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ require "fileutils"
4
+ require "formatador"
5
+
6
+ require "ostruct"
7
+ require "uuid"
8
+ require "json"
9
+ require "colorize"
10
+ require "etc"
11
+
12
+ require "invoker/version"
13
+ require "invoker/logger"
14
+ require "invoker/daemon"
15
+ require "invoker/cli"
16
+ require "invoker/dns_cache"
17
+ require "invoker/ipc"
18
+ require "invoker/power/config"
19
+ require "invoker/power/port_finder"
20
+ require "invoker/power/setup"
21
+ require "invoker/power/setup/linux_setup"
22
+ require "invoker/power/setup/osx_setup"
23
+ require "invoker/power/powerup"
24
+ require "invoker/errors"
25
+ require "invoker/parsers/procfile"
26
+ require "invoker/parsers/config"
27
+ require "invoker/commander"
28
+ require "invoker/process_manager"
29
+ require "invoker/command_worker"
30
+ require "invoker/reactor"
31
+ require "invoker/event/manager"
32
+ require "invoker/process_printer"
33
+
34
+ module Invoker
35
+ class << self
36
+ attr_accessor :config, :tail_watchers, :commander
37
+ attr_accessor :dns_cache, :daemonize, :nocolors, :certificate, :private_key
38
+
39
+ alias_method :daemonize?, :daemonize
40
+ alias_method :nocolors?, :nocolors
41
+
42
+ def darwin?
43
+ ruby_platform.downcase.include?("darwin")
44
+ end
45
+
46
+ def linux?
47
+ ruby_platform.downcase.include?("linux")
48
+ end
49
+
50
+ def ruby_platform
51
+ RUBY_PLATFORM
52
+ end
53
+
54
+ def load_invoker_config(file, port)
55
+ @config = Invoker::Parsers::Config.new(file, port)
56
+ @dns_cache = Invoker::DNSCache.new(@invoker_config)
57
+ @tail_watchers = Invoker::CLI::TailWatcher.new
58
+ @commander = Invoker::Commander.new
59
+ end
60
+
61
+ def close_socket(socket)
62
+ socket.close
63
+ rescue StandardError => error
64
+ Invoker::Logger.puts "Error removing socket #{error}"
65
+ end
66
+
67
+ def daemon
68
+ @daemon ||= Invoker::Daemon.new
69
+ end
70
+
71
+ def can_run_balancer?(throw_warning = true)
72
+ return true if File.exist?(Invoker::Power::Config.config_file)
73
+
74
+ if throw_warning
75
+ Invoker::Logger.puts("Invoker has detected setup has not been run. Domain feature will not work without running setup command.".colorize(:red))
76
+ end
77
+ false
78
+ end
79
+
80
+ def setup_config_location
81
+ config_dir = Invoker::Power::Config.config_dir
82
+ return config_dir if Dir.exist?(config_dir)
83
+
84
+ if File.exist?(config_dir)
85
+ old_config = File.read(config_dir)
86
+ FileUtils.rm_f(config_dir)
87
+ end
88
+
89
+ FileUtils.mkdir(config_dir)
90
+
91
+ migrate_old_config(old_config, config_dir) if old_config
92
+ config_dir
93
+ end
94
+
95
+ def run_without_bundler
96
+ if defined?(Bundler)
97
+ Bundler.with_unbundled_env do
98
+ yield
99
+ end
100
+ else
101
+ yield
102
+ end
103
+ end
104
+
105
+ def notify_user(message)
106
+ if Invoker.darwin?
107
+ run_without_bundler { check_and_notify_with_terminal_notifier(message) }
108
+ elsif Invoker.linux?
109
+ notify_with_libnotify(message)
110
+ end
111
+ end
112
+
113
+ def check_and_notify_with_terminal_notifier(message)
114
+ command_path = `which terminal-notifier`
115
+ if command_path && !command_path.empty?
116
+ system("terminal-notifier -message '#{message}' -title Invoker")
117
+ end
118
+ end
119
+
120
+ def notify_with_libnotify(message)
121
+ begin
122
+ require "libnotify"
123
+ Libnotify.show(body: message, summary: "Invoker", timeout: 2.5)
124
+ rescue LoadError; end
125
+ end
126
+
127
+ def migrate_old_config(old_config, config_location)
128
+ new_config = File.join(config_location, 'config')
129
+ File.open(new_config, 'w') do |file|
130
+ file.write(old_config)
131
+ end
132
+ end
133
+
134
+ # On some platforms `Dir.home` or `ENV['HOME']` does not return home directory of user.
135
+ # this is especially true, after effective and real user id of process
136
+ # has been changed.
137
+ #
138
+ # @return [String] home directory of the user
139
+ def home
140
+ if File.writable?(Dir.home)
141
+ Dir.home
142
+ else
143
+ Etc.getpwuid(Process.uid).dir
144
+ end
145
+ end
146
+
147
+ def default_tld
148
+ 'test'
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+
3
+ describe Invoker::CLI::Pinger do
4
+ let(:unix_client) { Invoker::IPC::UnixClient.new }
5
+ let(:pinger) { Invoker::CLI::Pinger.new(unix_client) }
6
+ let(:pong) { MM::Pong.new(status: 'pong') }
7
+
8
+ context "If Invoker is running" do
9
+ it "should return true" do
10
+ unix_client.expects(:send_and_receive).returns(pong)
11
+ expect(pinger.invoker_running?).to be_truthy
12
+ end
13
+ end
14
+
15
+ context "if Invoker is not running" do
16
+ it "should return false" do
17
+ unix_client.expects(:send_and_receive).returns(nil)
18
+ unix_client.expects(:abort).never
19
+ expect(pinger.invoker_running?).to be_falsey
20
+ end
21
+ end
22
+ end