invoker 1.4.1 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35e208abbd4ff8979f1d1ecc0c5896ef3b460799
|
4
|
+
data.tar.gz: 6e2e65d581a9705f5358bf8076654a9b34185683
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44eecb467482053d584410fbc279c192e1dc25b7c97f245bf058f20e7bac0a12d9c0c73487d0ab0652d632030ef3f39741449dd5d30391104ef4ec9cc165091f
|
7
|
+
data.tar.gz: a4108aab6742c8b02886423a341c2d59c47deba5645d73b671686aff4cac4f7af668677645bb5444b8d37fe260afa8e05631ca249ba9d41f6bc9396426534a30
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/Dockerfile
ADDED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -5,3 +5,11 @@ RSpec::Core::RakeTask.new
|
|
5
5
|
|
6
6
|
task :default => :spec
|
7
7
|
task :test => :spec
|
8
|
+
|
9
|
+
current_directory = File.expand_path(File.dirname(__FILE__))
|
10
|
+
|
11
|
+
desc "run specs inside docker"
|
12
|
+
task :docker_spec do
|
13
|
+
system("docker build -t invoker-ruby . ")
|
14
|
+
system("docker run --name invoker-rspec --rm -v #{current_directory}:/invoker -t invoker-ruby")
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# myapp.rb
|
2
|
+
require 'sinatra'
|
3
|
+
|
4
|
+
get '/' do
|
5
|
+
'Hello world!'
|
6
|
+
end
|
7
|
+
|
8
|
+
get "/emacs" do
|
9
|
+
redirect to("/vim")
|
10
|
+
end
|
11
|
+
|
12
|
+
get "/vim" do
|
13
|
+
"vim rules"
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
post '/foo' do
|
18
|
+
puts request.env
|
19
|
+
"done"
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
post "/api/v1/datapoints" do
|
24
|
+
puts request.env
|
25
|
+
"done"
|
26
|
+
end
|
data/examples/sample.ini
ADDED
data/invoker.gemspec
CHANGED
@@ -35,8 +35,9 @@ Gem::Specification.new do |s|
|
|
35
35
|
s.add_dependency("uuid", "~> 2.3")
|
36
36
|
s.add_dependency("facter", "~> 2.2")
|
37
37
|
s.add_dependency("http-parser-lite", "~> 0.6")
|
38
|
-
s.add_dependency("dotenv", "~>
|
38
|
+
s.add_dependency("dotenv", "~> 2.0")
|
39
39
|
s.add_development_dependency("rspec", "~> 3.0")
|
40
40
|
s.add_development_dependency("mocha")
|
41
41
|
s.add_development_dependency("rake")
|
42
|
+
s.add_development_dependency('fakefs')
|
42
43
|
end
|
data/lib/invoker.rb
CHANGED
@@ -44,6 +44,10 @@ module Invoker
|
|
44
44
|
ruby_platform.downcase.include?("darwin")
|
45
45
|
end
|
46
46
|
|
47
|
+
def linux?
|
48
|
+
ruby_platform.downcase.include?("linux")
|
49
|
+
end
|
50
|
+
|
47
51
|
def ruby_platform
|
48
52
|
RUBY_PLATFORM
|
49
53
|
end
|
@@ -100,18 +104,27 @@ module Invoker
|
|
100
104
|
end
|
101
105
|
|
102
106
|
def notify_user(message)
|
103
|
-
|
107
|
+
if Invoker.darwin?
|
108
|
+
run_without_bundler { check_and_notify_with_terminal_notifier(message) }
|
109
|
+
elsif Invoker.linux?
|
110
|
+
notify_with_libnotify(message)
|
111
|
+
end
|
104
112
|
end
|
105
113
|
|
106
114
|
def check_and_notify_with_terminal_notifier(message)
|
107
|
-
return unless Invoker.darwin?
|
108
|
-
|
109
115
|
command_path = `which terminal-notifier`
|
110
116
|
if command_path && !command_path.empty?
|
111
117
|
system("terminal-notifier -message '#{message}' -title Invoker")
|
112
118
|
end
|
113
119
|
end
|
114
120
|
|
121
|
+
def notify_with_libnotify(message)
|
122
|
+
begin
|
123
|
+
require "libnotify"
|
124
|
+
Libnotify.show(body: message, summary: "Invoker", timeout: 2.5)
|
125
|
+
rescue LoadError; end
|
126
|
+
end
|
127
|
+
|
115
128
|
def migrate_old_config(old_config, config_location)
|
116
129
|
new_config = File.join(config_location, 'config')
|
117
130
|
File.open(new_config, 'w') do |file|
|
@@ -131,5 +144,9 @@ module Invoker
|
|
131
144
|
Etc.getpwuid(Process.uid).dir
|
132
145
|
end
|
133
146
|
end
|
147
|
+
|
148
|
+
def default_tld
|
149
|
+
'dev'
|
150
|
+
end
|
134
151
|
end
|
135
152
|
end
|
data/lib/invoker/cli.rb
CHANGED
@@ -13,8 +13,11 @@ module Invoker
|
|
13
13
|
end
|
14
14
|
|
15
15
|
desc "setup", "Run Invoker setup"
|
16
|
+
option :tld,
|
17
|
+
type: :string,
|
18
|
+
banner: 'Configure invoker to use a different top level domain'
|
16
19
|
def setup
|
17
|
-
Invoker::Power::Setup.install
|
20
|
+
Invoker::Power::Setup.install(get_tld(options))
|
18
21
|
end
|
19
22
|
|
20
23
|
desc "version", "Print Invoker version"
|
@@ -39,7 +42,7 @@ module Invoker
|
|
39
42
|
port = options[:port] || 9000
|
40
43
|
Invoker.daemonize = options[:daemon]
|
41
44
|
Invoker.load_invoker_config(file, port)
|
42
|
-
|
45
|
+
warn_about_notification
|
43
46
|
warn_about_old_configuration
|
44
47
|
pinger = Invoker::CLI::Pinger.new(unix_socket)
|
45
48
|
abort("Invoker is already running".color(:red)) if pinger.invoker_running?
|
@@ -51,9 +54,9 @@ module Invoker
|
|
51
54
|
unix_socket.send_command('add', process_name: name)
|
52
55
|
end
|
53
56
|
|
54
|
-
desc "add_http process_name port", "Add an external http process to Invoker DNS server"
|
55
|
-
def add_http(name, port)
|
56
|
-
unix_socket.send_command('add_http', process_name: name, port: port)
|
57
|
+
desc "add_http process_name port [IP]", "Add an external http process to Invoker DNS server"
|
58
|
+
def add_http(name, port, ip = nil)
|
59
|
+
unix_socket.send_command('add_http', process_name: name, port: port, ip: ip)
|
57
60
|
end
|
58
61
|
|
59
62
|
desc "tail process1 process2", "Tail a particular process"
|
@@ -105,12 +108,35 @@ module Invoker
|
|
105
108
|
tasks.keys + ["help"]
|
106
109
|
end
|
107
110
|
|
111
|
+
def get_tld(options)
|
112
|
+
if options[:tld] && !options[:tld].empty?
|
113
|
+
options[:tld]
|
114
|
+
else
|
115
|
+
'dev'
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
108
119
|
def unix_socket
|
109
120
|
Invoker::IPC::UnixClient.new
|
110
121
|
end
|
111
122
|
|
123
|
+
def warn_about_notification
|
124
|
+
if Invoker.darwin?
|
125
|
+
warn_about_terminal_notifier
|
126
|
+
else
|
127
|
+
warn_about_libnotify
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def warn_about_libnotify
|
132
|
+
require "libnotify"
|
133
|
+
rescue LoadError
|
134
|
+
Invoker::Logger.puts "You can install libnotify gem for Invoker notifications "\
|
135
|
+
"via system tray".color(:red)
|
136
|
+
end
|
137
|
+
|
112
138
|
def warn_about_terminal_notifier
|
113
|
-
if
|
139
|
+
if Invoker.darwin?
|
114
140
|
command_path = `which terminal-notifier`
|
115
141
|
if !command_path || command_path.empty?
|
116
142
|
Invoker::Logger.puts "You can enable OSX notification for processes "\
|
data/lib/invoker/dns_cache.rb
CHANGED
@@ -16,8 +16,8 @@ module Invoker
|
|
16
16
|
@dns_mutex.synchronize { dns_data[process_name] }
|
17
17
|
end
|
18
18
|
|
19
|
-
def add(name, port)
|
20
|
-
@dns_mutex.synchronize { dns_data[name] = { 'port' => port } }
|
19
|
+
def add(name, port, ip = nil)
|
20
|
+
@dns_mutex.synchronize { dns_data[name] = { 'port' => port, 'ip' => ip } }
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -2,7 +2,7 @@ module Invoker
|
|
2
2
|
module IPC
|
3
3
|
class AddHttpCommand < BaseCommand
|
4
4
|
def run_command(message_object)
|
5
|
-
Invoker.dns_cache.add(message_object.process_name, message_object.port)
|
5
|
+
Invoker.dns_cache.add(message_object.process_name, message_object.port, message_object.ip)
|
6
6
|
true
|
7
7
|
end
|
8
8
|
end
|
@@ -6,7 +6,8 @@ module Invoker
|
|
6
6
|
|
7
7
|
dns_check_response = Invoker::IPC::Message::DnsCheckResponse.new(
|
8
8
|
process_name: message_object.process_name,
|
9
|
-
port: process_detail ? process_detail['port'] : nil
|
9
|
+
port: process_detail ? process_detail['port'] : nil,
|
10
|
+
ip: process_detail && process_detail['ip'] ? process_detail['ip'] : '0.0.0.0'
|
10
11
|
)
|
11
12
|
send_data(dns_check_response)
|
12
13
|
true
|
data/lib/invoker/ipc/message.rb
CHANGED
@@ -118,7 +118,7 @@ module Invoker
|
|
118
118
|
|
119
119
|
class AddHttp < Base
|
120
120
|
include Serialization
|
121
|
-
message_attributes :process_name, :port
|
121
|
+
message_attributes :process_name, :port, :ip
|
122
122
|
end
|
123
123
|
|
124
124
|
class Reload < Base
|
@@ -151,7 +151,7 @@ module Invoker
|
|
151
151
|
|
152
152
|
class DnsCheckResponse < Base
|
153
153
|
include Serialization
|
154
|
-
message_attributes :process_name, :port
|
154
|
+
message_attributes :process_name, :port, :ip
|
155
155
|
end
|
156
156
|
|
157
157
|
class Ping < Base
|
@@ -16,7 +16,6 @@ module Invoker
|
|
16
16
|
# value by 1, that way generating different ports for different commands.
|
17
17
|
def initialize(filename, port)
|
18
18
|
@filename = filename || autodetect_config_file
|
19
|
-
|
20
19
|
print_message_and_abort if invalid_config_file?
|
21
20
|
|
22
21
|
@port = port - 1
|
@@ -38,6 +37,10 @@ module Invoker
|
|
38
37
|
power_config && power_config.https_port
|
39
38
|
end
|
40
39
|
|
40
|
+
def tld
|
41
|
+
power_config && power_config.tld
|
42
|
+
end
|
43
|
+
|
41
44
|
def autorunnable_processes
|
42
45
|
processes.reject(&:disable_autorun)
|
43
46
|
end
|
@@ -22,7 +22,7 @@ module Invoker
|
|
22
22
|
end
|
23
23
|
|
24
24
|
class Balancer
|
25
|
-
attr_accessor :connection, :http_parser, :session, :protocol
|
25
|
+
attr_accessor :connection, :http_parser, :session, :protocol, :upgraded_to
|
26
26
|
|
27
27
|
def self.run(options = {})
|
28
28
|
start_http_proxy(InvokerHttpProxy, 'http', options)
|
@@ -43,6 +43,7 @@ module Invoker
|
|
43
43
|
@protocol = protocol
|
44
44
|
@http_parser = HttpParser.new(protocol)
|
45
45
|
@session = nil
|
46
|
+
@upgraded_to = nil
|
46
47
|
@buffer = []
|
47
48
|
end
|
48
49
|
|
@@ -71,7 +72,7 @@ module Invoker
|
|
71
72
|
|
72
73
|
dns_check_response = UrlRewriter.new.select_backend_config(headers['Host'])
|
73
74
|
if dns_check_response && dns_check_response.port
|
74
|
-
connection.server(session, host:
|
75
|
+
connection.server(session, host: dns_check_response.ip, port: dns_check_response.port)
|
75
76
|
else
|
76
77
|
return_error_page(404)
|
77
78
|
http_parser.reset
|
@@ -80,8 +81,12 @@ module Invoker
|
|
80
81
|
end
|
81
82
|
|
82
83
|
def upstream_data(data)
|
83
|
-
|
84
|
-
|
84
|
+
if upgraded_to == "websocket"
|
85
|
+
data
|
86
|
+
else
|
87
|
+
append_for_http_parsing(data)
|
88
|
+
nil
|
89
|
+
end
|
85
90
|
end
|
86
91
|
|
87
92
|
def append_for_http_parsing(data)
|
@@ -93,6 +98,13 @@ module Invoker
|
|
93
98
|
|
94
99
|
def backend_data(backend, data)
|
95
100
|
@backend_data = true
|
101
|
+
|
102
|
+
# check backend data for websockets connection. check for upgrade headers
|
103
|
+
# - Upgarde: websocket\r\n
|
104
|
+
if data =~ /Upgrade: websocket/
|
105
|
+
@upgraded_to = "websocket"
|
106
|
+
end
|
107
|
+
|
96
108
|
data
|
97
109
|
end
|
98
110
|
|
data/lib/invoker/power/config.rb
CHANGED
@@ -60,9 +60,10 @@ module Invoker
|
|
60
60
|
def dns_port; @config[:dns_port]; end
|
61
61
|
def http_port; @config[:http_port]; end
|
62
62
|
def ipfw_rule_number; @config[:ipfw_rule_number]; end
|
63
|
+
def https_port; @config[:https_port]; end
|
63
64
|
|
64
|
-
def
|
65
|
-
@config[:
|
65
|
+
def tld
|
66
|
+
@config[:tld] || Invoker.default_tld
|
66
67
|
end
|
67
68
|
|
68
69
|
def save
|
data/lib/invoker/power/dns.rb
CHANGED
@@ -13,7 +13,7 @@ module Invoker
|
|
13
13
|
def migrate
|
14
14
|
if firewall_config_requires_migration? && ask_user_for_migration
|
15
15
|
sudome
|
16
|
-
osx_setup = Invoker::Power::OsxSetup.new()
|
16
|
+
osx_setup = Invoker::Power::OsxSetup.new(Invoker.config.tld)
|
17
17
|
osx_setup.install_firewall(Invoker.config.http_port, Invoker.config.https_port)
|
18
18
|
drop_to_normal_user
|
19
19
|
Invoker::Logger.puts "Invoker has updated its configuration for yosemite."\
|
data/lib/invoker/power/setup.rb
CHANGED
@@ -3,15 +3,17 @@ require "eventmachine"
|
|
3
3
|
module Invoker
|
4
4
|
module Power
|
5
5
|
class Setup
|
6
|
-
attr_accessor :port_finder
|
7
|
-
|
6
|
+
attr_accessor :port_finder, :tld
|
7
|
+
|
8
|
+
def self.install(tld)
|
8
9
|
selected_installer_klass = installer_klass
|
9
|
-
selected_installer_klass.new.install
|
10
|
+
selected_installer_klass.new(tld).install
|
10
11
|
end
|
11
12
|
|
12
13
|
def self.uninstall
|
14
|
+
power_config = Invoker::Power::Config.load_config
|
13
15
|
selected_installer_klass = installer_klass
|
14
|
-
selected_installer_klass.new.uninstall_invoker
|
16
|
+
selected_installer_klass.new(power_config.tld).uninstall_invoker
|
15
17
|
end
|
16
18
|
|
17
19
|
def self.installer_klass
|
@@ -22,6 +24,14 @@ module Invoker
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
27
|
+
def initialize(tld)
|
28
|
+
if tld !~ /^[a-z]+$/
|
29
|
+
Invoker::Logger.puts("Please specify valid tld".color(:red))
|
30
|
+
exit(1)
|
31
|
+
end
|
32
|
+
self.tld = tld
|
33
|
+
end
|
34
|
+
|
25
35
|
def install
|
26
36
|
if check_if_setup_can_run?
|
27
37
|
setup_invoker
|
@@ -46,6 +56,35 @@ module Invoker
|
|
46
56
|
def check_if_setup_can_run?
|
47
57
|
!File.exists?(Invoker::Power::Config.config_file)
|
48
58
|
end
|
59
|
+
|
60
|
+
def create_config_file
|
61
|
+
Invoker.setup_config_location
|
62
|
+
config = build_power_config
|
63
|
+
Invoker::Power::Config.create(config)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Builds and returns power config hash. Override this method in subclasses if necessary.
|
67
|
+
def build_power_config
|
68
|
+
config = {
|
69
|
+
http_port: port_finder.http_port,
|
70
|
+
https_port: port_finder.https_port,
|
71
|
+
tld: tld
|
72
|
+
}
|
73
|
+
config
|
74
|
+
end
|
75
|
+
|
76
|
+
def remove_resolver_file
|
77
|
+
begin
|
78
|
+
safe_remove_file(resolver_file)
|
79
|
+
rescue Errno::EACCES
|
80
|
+
Invoker::Logger.puts("Running uninstall requires root access, please rerun it with sudo".color(:red))
|
81
|
+
raise
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def safe_remove_file(file)
|
86
|
+
File.delete(file) if File.exists?(file)
|
87
|
+
end
|
49
88
|
end
|
50
89
|
end
|
51
90
|
end
|