invoker 1.1.0 → 1.2.0.pre

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 17e01fb0ade988c21a62f385d51e3b07e58f9016
4
- data.tar.gz: 2e4e0c36f2df111493b7c05dea7e0ae99244de2c
3
+ metadata.gz: 82fe57088b14eea68ff54c85fd7cb0d95ab005d2
4
+ data.tar.gz: 37b082192e6af1f57544055d9a3c65761b53dbfc
5
5
  SHA512:
6
- metadata.gz: a7601b89cd0db7b1cc0e780885d14f27ec652739702b5c2a59cf961b677db347bfd9e764ada4a53057de80a418ca3d486949c1a6909ee414505a8b5323593708
7
- data.tar.gz: 552b15ffb14c384d02f3ec972ccd8f3a2191afedab5bfa899f19c9fb1ecf0e4df86c65cdbfa475df8babfc746401bc6d914bcb26f0abda2f6fd04283dab092c3
6
+ metadata.gz: 9840525fee76d6639a1a138d3fa4a0b40f4a9f197acf73a47a79c02cc01a67c523bb21559457bd0ab32cbf9f604fb557a69e95c610d3c60b90d2bac09d8114ea
7
+ data.tar.gz: 75622356bdde370032362506609019947b439d0cfcb16ba70de758b4ada5797668f8abf1552afa9f37ecf6dec465e281d2b0fe54dc6f52d65f3c595db96b969c
data/.gitignore CHANGED
@@ -3,8 +3,7 @@ config/
3
3
  *.gem
4
4
  Gemfile.lock
5
5
  pkg/
6
- local.ini
7
- multi.ini
6
+ *.ini
8
7
  tags
9
8
  .rvmrc
10
9
  vendor/
@@ -13,3 +12,4 @@ _site
13
12
  coverage
14
13
  invoker_profile/
15
14
  *.pid
15
+ .ruby-version
@@ -18,6 +18,8 @@ require "invoker/ipc"
18
18
  require "invoker/power/config"
19
19
  require "invoker/power/port_finder"
20
20
  require "invoker/power/setup"
21
+ require "invoker/power/setup/linux_setup"
22
+ require "invoker/power/setup/osx_setup"
21
23
  require "invoker/power/powerup"
22
24
  require "invoker/errors"
23
25
  require "invoker/parsers/procfile"
@@ -62,7 +64,6 @@ module Invoker
62
64
  end
63
65
 
64
66
  def can_run_balancer?(throw_warning = true)
65
- return false unless darwin?
66
67
  return true if File.exist?(Invoker::Power::Config::CONFIG_LOCATION)
67
68
 
68
69
  if throw_warning
@@ -23,6 +23,10 @@ module Invoker
23
23
  power_config && power_config.dns_port
24
24
  end
25
25
 
26
+ def https_port
27
+ power_config && power_config.https_port
28
+ end
29
+
26
30
  def process(label)
27
31
  processes.detect { |pconfig| pconfig.label == label }
28
32
  end
@@ -3,7 +3,7 @@ require 'http-parser'
3
3
 
4
4
  module Invoker
5
5
  module Power
6
- class BalancerConnection < EventMachine::ProxyServer::Connection
6
+ class InvokerHttpProxy < EventMachine::ProxyServer::Connection
7
7
  attr_accessor :host, :ip, :port
8
8
  def set_host(host, selected_backend)
9
9
  self.host = host
@@ -12,6 +12,13 @@ module Invoker
12
12
  end
13
13
  end
14
14
 
15
+ class InvokerHttpsProxy < InvokerHttpProxy
16
+ def post_init
17
+ super
18
+ start_tls
19
+ end
20
+ end
21
+
15
22
  class BalancerParser
16
23
  attr_accessor :host, :parser
17
24
  def initialize
@@ -44,27 +51,44 @@ module Invoker
44
51
  end
45
52
 
46
53
  class Balancer
47
- attr_accessor :connection, :http_parser, :session
54
+ attr_accessor :connection, :http_parser, :session, :protocol
48
55
  DEV_MATCH_REGEX = /([\w-]+)\.dev(\:\d+)?$/
49
56
 
50
57
  def self.run(options = {})
51
- EventMachine.start_server('0.0.0.0', Invoker.config.http_port,
52
- BalancerConnection, options) do |connection|
53
- balancer = Balancer.new(connection)
58
+ start_http_proxy(InvokerHttpProxy, 'http', options)
59
+ start_http_proxy(InvokerHttpsProxy, 'https', options)
60
+ end
61
+
62
+ def self.start_http_proxy(proxy_class, protocol, options)
63
+ port = protocol == 'http' ? Invoker.config.http_port : Invoker.config.https_port
64
+ EventMachine.start_server('0.0.0.0', port,
65
+ proxy_class, options) do |connection|
66
+ balancer = Balancer.new(connection, protocol)
54
67
  balancer.install_callbacks
55
68
  end
56
69
  end
57
70
 
58
- def initialize(connection)
71
+ def initialize(connection, protocol)
59
72
  @connection = connection
73
+ @protocol = protocol
60
74
  @http_parser = BalancerParser.new()
61
75
  @session = nil
62
76
  @buffer = []
63
77
  end
64
78
 
79
+ # insert X_FORWARDED_PROTO_ so as rails can identify the request as coming from
80
+ # https
81
+ def insert_forwarded_proto_header(data)
82
+ if data =~ /\r\n\r\n/ && data !~ /X_FORWARDED_PROTO/i && protocol == 'https'
83
+ data.gsub(/\r\n\r\n/, "\r\nX_FORWARDED_PROTO: #{protocol}\r\n\r\n")
84
+ else
85
+ data
86
+ end
87
+ end
88
+
65
89
  def install_callbacks
66
90
  http_parser.on_headers_complete { |header| headers_received(header) }
67
- connection.on_data {|data| upstream_data(data) }
91
+ connection.on_data { |data| upstream_data(data) }
68
92
  connection.on_response { |backend, data| backend_data(backend, data) }
69
93
  connection.on_finish { |backend, name| frontend_disconnect(backend, name) }
70
94
  end
@@ -74,7 +98,7 @@ module Invoker
74
98
  dns_check_response = select_backend_config(header['Host'])
75
99
  if dns_check_response && dns_check_response.port
76
100
  connection.server(session, host: '0.0.0.0', port: dns_check_response.port)
77
- connection.relay_to_servers(@buffer.join)
101
+ connection.relay_to_servers(insert_forwarded_proto_header(@buffer.join))
78
102
  @buffer = []
79
103
  else
80
104
  return_error_page(404)
@@ -88,7 +112,7 @@ module Invoker
88
112
  append_for_http_parsing(data)
89
113
  nil
90
114
  else
91
- data
115
+ insert_forwarded_proto_header(data)
92
116
  end
93
117
  end
94
118
 
@@ -107,7 +131,7 @@ module Invoker
107
131
  def frontend_disconnect(backend, name)
108
132
  http_parser.reset
109
133
  unless @backend_data
110
- Invoker::Logger.puts("\nApplication not running. Returning error page.".color(:red))
134
+ Invoker::Logger.puts("\nApplication #{name} not running. Returning error page.".color(:red))
111
135
  return_error_page(503)
112
136
  end
113
137
  @backend_data = false
@@ -43,6 +43,10 @@ module Invoker
43
43
  @config[:http_port] = http_port
44
44
  end
45
45
 
46
+ def https_port=(https_port)
47
+ @config[:https_port] = https_port
48
+ end
49
+
46
50
  def ipfw_rule_number=(ipfw_rule_number)
47
51
  @config[:ipfw_rule_number] = ipfw_rule_number
48
52
  end
@@ -51,6 +55,10 @@ module Invoker
51
55
  def http_port; @config[:http_port]; end
52
56
  def ipfw_rule_number; @config[:ipfw_rule_number]; end
53
57
 
58
+ def https_port
59
+ @config[:https_port]
60
+ end
61
+
54
62
  def save
55
63
  File.open(CONFIG_LOCATION, "w") do |fl|
56
64
  YAML.dump(@config, fl)
@@ -2,7 +2,7 @@ module Invoker
2
2
  module Power
3
3
  class PortFinder
4
4
  STARTING_PORT = 23400
5
- attr_accessor :dns_port, :http_port, :starting_port
5
+ attr_accessor :dns_port, :http_port, :starting_port, :https_port
6
6
  def initialize
7
7
  @starting_port = STARTING_PORT
8
8
  @ports = []
@@ -12,7 +12,7 @@ module Invoker
12
12
 
13
13
  def find_ports
14
14
  STARTING_PORT.upto(STARTING_PORT + 100) do |port|
15
- break if @ports.size > 2
15
+ break if @ports.size > 3
16
16
  if check_if_port_is_open(port)
17
17
  @ports << port
18
18
  else
@@ -21,9 +21,11 @@ module Invoker
21
21
  end
22
22
  @dns_port = @ports[0]
23
23
  @http_port = @ports[1]
24
+ @https_port = @ports[2]
24
25
  end
25
26
 
26
27
  private
28
+
27
29
  def check_if_port_is_open(port)
28
30
  socket_flag = true
29
31
  sockets = nil
@@ -42,8 +44,6 @@ module Invoker
42
44
  rescue
43
45
  nil
44
46
  end
45
-
46
-
47
47
  end
48
48
  end
49
49
  end
@@ -13,7 +13,9 @@ module Invoker
13
13
  EM.run {
14
14
  trap("TERM") { stop }
15
15
  trap("INT") { stop }
16
- DNS.new.run(listen: DNS.server_ports)
16
+ if Invoker.darwin?
17
+ DNS.new.run(listen: DNS.server_ports)
18
+ end
17
19
  Balancer.run
18
20
  }
19
21
  end
@@ -3,72 +3,38 @@ require "eventmachine"
3
3
  module Invoker
4
4
  module Power
5
5
  class Setup
6
- RESOLVER_FILE = "/etc/resolver/dev"
7
- RESOLVER_DIR = "/etc/resolver"
8
-
9
- FIREWALL_PLIST_FILE = "/Library/LaunchDaemons/com.codemancers.invoker.firewall.plist"
6
+ attr_accessor :port_finder
10
7
  def self.install
11
- installer = new
12
- if Invoker.darwin?
13
- if installer.check_if_setup_can_run?
14
- installer.setup_invoker
15
- else
16
- Invoker::Logger.puts("The setup has been already run.".color(:red))
17
- end
18
- else
19
- Invoker::Logger.puts("Domain feature is currently not supported on systems other than OSX".color(:red))
20
- end
21
- installer
8
+ selected_installer_klass = installer_klass
9
+ selected_installer_klass.new.install
22
10
  end
23
11
 
24
12
  def self.uninstall
25
- installer = new
26
- installer.uninstall_invoker
13
+ selected_installer_klass = installer_klass
14
+ selected_installer_klass.new.uninstall_invoker
27
15
  end
28
16
 
29
- def setup_invoker
30
- if setup_resolver_file
31
- find_open_ports
32
- install_resolver(port_finder.dns_port)
33
- install_firewall(port_finder.http_port)
34
- flush_dns_rules()
35
- # Before writing the config file, drop down to a normal user
36
- drop_to_normal_user()
37
- create_config_file()
17
+ def self.installer_klass
18
+ if Invoker.darwin?
19
+ Invoker::Power::OsxSetup
38
20
  else
39
- Invoker::Logger.puts("Invoker is not configured to serve from subdomains".color(:red))
21
+ Invoker::Power::LinuxSetup
40
22
  end
41
- self
42
23
  end
43
24
 
44
- def uninstall_invoker
45
- uninstall_invoker_flag = Invoker::CLI::Question.agree("Are you sure you want to uninstall firewall rules created by setup (y/n) : ")
46
-
47
- if uninstall_invoker_flag
48
- remove_resolver_file
49
- unload_firewall_rule(true)
50
- flush_dns_rules
51
- Invoker::Power::Config.delete
52
- Invoker::Logger.puts("Firewall rules were removed")
25
+ def install
26
+ if check_if_setup_can_run?
27
+ setup_invoker
28
+ else
29
+ Invoker::Logger.puts("The setup has been already run.".color(:red))
53
30
  end
31
+ self
54
32
  end
55
33
 
56
34
  def drop_to_normal_user
57
35
  EventMachine.set_effective_user(ENV["SUDO_USER"])
58
36
  end
59
37
 
60
- def flush_dns_rules
61
- system("dscacheutil -flushcache")
62
- end
63
-
64
- def create_config_file
65
- Invoker.setup_config_location
66
- Invoker::Power::Config.create(
67
- dns_port: port_finder.dns_port,
68
- http_port: port_finder.http_port
69
- )
70
- end
71
-
72
38
  def find_open_ports
73
39
  port_finder.find_ports()
74
40
  end
@@ -77,112 +43,9 @@ module Invoker
77
43
  @port_finder ||= Invoker::Power::PortFinder.new()
78
44
  end
79
45
 
80
- def install_resolver(dns_port)
81
- open_resolver_for_write { |fl|
82
- fl.write(resolve_string(dns_port))
83
- }
84
- rescue Errno::EACCES
85
- Invoker::Logger.puts("Running setup requires root access, please rerun it with sudo".color(:red))
86
- raise
87
- end
88
-
89
- def remove_resolver_file
90
- if File.exists?(RESOLVER_FILE)
91
- File.delete(RESOLVER_FILE)
92
- end
93
- rescue Errno::EACCES
94
- Invoker::Logger.puts("Running uninstall requires root access, please rerun it with sudo".color(:red))
95
- raise
96
- end
97
-
98
46
  def check_if_setup_can_run?
99
47
  !File.exists?(Invoker::Power::Config::CONFIG_LOCATION)
100
48
  end
101
-
102
- def install_firewall(balancer_port)
103
- File.open(FIREWALL_PLIST_FILE, "w") { |fl|
104
- fl.write(plist_string(balancer_port))
105
- }
106
- unload_firewall_rule
107
- load_firewall_rule
108
- end
109
-
110
- def load_firewall_rule
111
- system("launchctl load -Fw #{FIREWALL_PLIST_FILE} 2>/dev/null")
112
- end
113
-
114
- def unload_firewall_rule(remove = false)
115
- system("launchctl unload -w #{FIREWALL_PLIST_FILE} 2>/dev/null")
116
- system("rm -rf #{FIREWALL_PLIST_FILE}") if remove
117
- end
118
-
119
- # Ripped from POW code
120
- def plist_string(balancer_port)
121
- plist =<<-EOD
122
- <?xml version="1.0" encoding="UTF-8"?>
123
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
124
- <plist version="1.0">
125
- <dict>
126
- <key>Label</key>
127
- <string>com.codemancers.invoker</string>
128
- <key>ProgramArguments</key>
129
- <array>
130
- <string>sh</string>
131
- <string>-c</string>
132
- <string>#{firewall_command(balancer_port)}</string>
133
- </array>
134
- <key>RunAtLoad</key>
135
- <true/>
136
- <key>UserName</key>
137
- <string>root</string>
138
- </dict>
139
- </plist>
140
- EOD
141
- plist
142
- end
143
-
144
- def resolve_string(dns_port)
145
- string =<<-EOD
146
- nameserver 127.0.0.1
147
- port #{dns_port}
148
- EOD
149
- string
150
- end
151
-
152
- # Ripped from Pow code
153
- def firewall_command(balancer_port)
154
- "ipfw add fwd 127.0.0.1,#{balancer_port} tcp from any to me dst-port 80 in"\
155
- "&amp;&amp; sysctl -w net.inet.ip.forwarding=1"
156
- end
157
-
158
- def setup_resolver_file
159
- return true unless File.exists?(RESOLVER_FILE)
160
- Invoker::Logger.puts "Invoker has detected an existing Pow installation. We recommend "\
161
- "that you uninstall pow and rerun this setup.".color(:red)
162
-
163
- Invoker::Logger.puts "If you have already uninstalled Pow, proceed with installation"\
164
- " by pressing y/n."
165
-
166
- replace_resolver_flag = Invoker::CLI::Question.agree("Replace Pow configuration (y/n) : ")
167
-
168
- if replace_resolver_flag
169
- Invoker::Logger.puts "Invoker has overwritten one or more files created by Pow. "\
170
- "If .dev domains still don't resolve locally. Try turning off the wi-fi"\
171
- " and turning it on. It will force OSX to reload network configuration".color(:green)
172
- end
173
- replace_resolver_flag
174
- end
175
-
176
- private
177
-
178
- def open_resolver_for_write
179
- FileUtils.mkdir(RESOLVER_DIR) unless Dir.exists?(RESOLVER_DIR)
180
- fl = File.open(RESOLVER_FILE, "w")
181
- yield fl
182
- ensure
183
- fl && fl.close
184
- end
185
-
186
49
  end
187
50
  end
188
51
  end
@@ -0,0 +1,84 @@
1
+ module Invoker
2
+ module Power
3
+ class LinuxSetup < Setup
4
+ RESOLVER_FILE = "/etc/dnsmasq.d/dev-tld"
5
+ RINETD_FILE = "/etc/rinetd.conf"
6
+
7
+ def setup_invoker
8
+ if get_user_confirmation?
9
+ find_open_ports
10
+ install_required_software
11
+ install_resolver
12
+ install_port_forwarder
13
+ restart_services
14
+ drop_to_normal_user
15
+ create_config_file
16
+ else
17
+ Invoker::Logger.puts("Invoker is not configured to serve from subdomains".color(:red))
18
+ end
19
+ self
20
+ end
21
+
22
+ def create_config_file
23
+ Invoker.setup_config_location
24
+ Invoker::Power::Config.create(
25
+ http_port: port_finder.http_port,
26
+ https_port: port_finder.https_port
27
+ )
28
+ end
29
+
30
+ def uninstall_invoker
31
+ Invoker::Logger.puts("Uninstall is not yet supported on Linux."\
32
+ " You can remove invoker changes by uninstalling dnsmasq and rinetd")
33
+ end
34
+
35
+ private
36
+
37
+ def restart_services
38
+ system("/etc/init.d/rinetd restart")
39
+ system("/etc/init.d/dnsmasq restart")
40
+ end
41
+
42
+ def install_required_software
43
+ system("apt-get --assume-yes install dnsmasq rinetd")
44
+ end
45
+
46
+ def install_resolver
47
+ File.open(RESOLVER_FILE, "w") do |fl|
48
+ fl.write(tld_setup)
49
+ end
50
+ end
51
+
52
+ def install_port_forwarder
53
+ File.open(RINETD_FILE, "a") do |fl|
54
+ fl << "\n"
55
+ fl << rinetd_setup(port_finder.http_port, port_finder.https_port)
56
+ end
57
+ end
58
+
59
+ def tld_setup
60
+ tld_string =<<-EOD
61
+ local=/dev/
62
+ address=/dev/127.0.0.1
63
+ EOD
64
+ tld_string
65
+ end
66
+
67
+ def rinetd_setup(http_port, https_port)
68
+ rinetd_string =<<-EOD
69
+ 0.0.0.0 80 0.0.0.0 #{http_port}
70
+ 0.0.0.0 443 0.0.0.0 #{https_port}
71
+ EOD
72
+ rinetd_string
73
+ end
74
+
75
+ def get_user_confirmation?
76
+ Invoker::Logger.puts("Invoker is going to install dnsmasq and rinetd on this machine."\
77
+ " It is also going to install a local resolver for .dev domain and a rinetd rule"\
78
+ " which will forward all local requests on port 80 and 443 to another port")
79
+ Invoker::Logger.puts("If you still want to proceed with installation, press y.")
80
+ Invoker::CLI::Question.agree("Proceed with installation (y/n) : ")
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,152 @@
1
+ module Invoker
2
+ module Power
3
+ class OsxSetup < Setup
4
+ RESOLVER_FILE = "/etc/resolver/dev"
5
+ RESOLVER_DIR = "/etc/resolver"
6
+ FIREWALL_PLIST_FILE = "/Library/LaunchDaemons/com.codemancers.invoker.firewall.plist"
7
+
8
+ def setup_invoker
9
+ if setup_resolver_file
10
+ find_open_ports
11
+ install_resolver(port_finder.dns_port)
12
+ install_firewall(port_finder.http_port, port_finder.https_port)
13
+ flush_dns_rules
14
+ # Before writing the config file, drop down to a normal user
15
+ drop_to_normal_user
16
+ create_config_file
17
+ else
18
+ Invoker::Logger.puts("Invoker is not configured to serve from subdomains".color(:red))
19
+ end
20
+ self
21
+ end
22
+
23
+ def uninstall_invoker
24
+ uninstall_invoker_flag = Invoker::CLI::Question.agree("Are you sure you want to uninstall firewall rules created by setup (y/n) : ")
25
+
26
+ if uninstall_invoker_flag
27
+ remove_resolver_file
28
+ unload_firewall_rule(true)
29
+ flush_dns_rules
30
+ Invoker::Power::Config.delete
31
+ Invoker::Logger.puts("Firewall rules were removed")
32
+ end
33
+ end
34
+
35
+ def flush_dns_rules
36
+ system("dscacheutil -flushcache")
37
+ end
38
+
39
+ def create_config_file
40
+ Invoker.setup_config_location
41
+ Invoker::Power::Config.create(
42
+ dns_port: port_finder.dns_port,
43
+ http_port: port_finder.http_port,
44
+ https_port: port_finder.https_port
45
+ )
46
+ end
47
+
48
+ def install_resolver(dns_port)
49
+ open_resolver_for_write { |fl|
50
+ fl.write(resolve_string(dns_port))
51
+ }
52
+ rescue Errno::EACCES
53
+ Invoker::Logger.puts("Running setup requires root access, please rerun it with sudo".color(:red))
54
+ raise
55
+ end
56
+
57
+ def remove_resolver_file
58
+ if File.exists?(RESOLVER_FILE)
59
+ File.delete(RESOLVER_FILE)
60
+ end
61
+ rescue Errno::EACCES
62
+ Invoker::Logger.puts("Running uninstall requires root access, please rerun it with sudo".color(:red))
63
+ raise
64
+ end
65
+
66
+ def install_firewall(http_port, https_port)
67
+ File.open(FIREWALL_PLIST_FILE, "w") { |fl|
68
+ fl.write(plist_string(http_port, https_port))
69
+ }
70
+ unload_firewall_rule
71
+ load_firewall_rule
72
+ end
73
+
74
+ def load_firewall_rule
75
+ system("launchctl load -Fw #{FIREWALL_PLIST_FILE} 2>/dev/null")
76
+ end
77
+
78
+ def unload_firewall_rule(remove = false)
79
+ system("launchctl unload -w #{FIREWALL_PLIST_FILE} 2>/dev/null")
80
+ system("rm -rf #{FIREWALL_PLIST_FILE}") if remove
81
+ end
82
+
83
+ # Ripped from POW code
84
+ def plist_string(http_port, https_port)
85
+ plist =<<-EOD
86
+ <?xml version="1.0" encoding="UTF-8"?>
87
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
88
+ <plist version="1.0">
89
+ <dict>
90
+ <key>Label</key>
91
+ <string>com.codemancers.invoker</string>
92
+ <key>ProgramArguments</key>
93
+ <array>
94
+ <string>sh</string>
95
+ <string>-c</string>
96
+ <string>#{firewall_command(http_port, https_port)}</string>
97
+ </array>
98
+ <key>RunAtLoad</key>
99
+ <true/>
100
+ <key>UserName</key>
101
+ <string>root</string>
102
+ </dict>
103
+ </plist>
104
+ EOD
105
+ plist
106
+ end
107
+
108
+ def resolve_string(dns_port)
109
+ string =<<-EOD
110
+ nameserver 127.0.0.1
111
+ port #{dns_port}
112
+ EOD
113
+ string
114
+ end
115
+
116
+ # Ripped from Pow code
117
+ def firewall_command(http_port, https_port)
118
+ "ipfw add fwd 127.0.0.1,#{http_port} tcp from any to me dst-port 80 in"\
119
+ "&amp;&amp; ipfw add fwd 127.0.0.1,#{https_port} tcp from any to me dst-port 443 in"\
120
+ "&amp;&amp; sysctl -w net.inet.ip.forwarding=1"
121
+ end
122
+
123
+ def setup_resolver_file
124
+ return true unless File.exists?(RESOLVER_FILE)
125
+ Invoker::Logger.puts "Invoker has detected an existing Pow installation. We recommend "\
126
+ "that you uninstall pow and rerun this setup.".color(:red)
127
+
128
+ Invoker::Logger.puts "If you have already uninstalled Pow, proceed with installation"\
129
+ " by pressing y/n."
130
+
131
+ replace_resolver_flag = Invoker::CLI::Question.agree("Replace Pow configuration (y/n) : ")
132
+
133
+ if replace_resolver_flag
134
+ Invoker::Logger.puts "Invoker has overwritten one or more files created by Pow. "\
135
+ "If .dev domains still don't resolve locally. Try turning off the wi-fi"\
136
+ " and turning it on. It will force OSX to reload network configuration".color(:green)
137
+ end
138
+ replace_resolver_flag
139
+ end
140
+
141
+ private
142
+
143
+ def open_resolver_for_write
144
+ FileUtils.mkdir(RESOLVER_DIR) unless Dir.exists?(RESOLVER_DIR)
145
+ fl = File.open(RESOLVER_FILE, "w")
146
+ yield fl
147
+ ensure
148
+ fl && fl.close
149
+ end
150
+ end
151
+ end
152
+ end
@@ -1,3 +1,3 @@
1
1
  module Invoker
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0.pre"
3
3
  end
@@ -108,20 +108,12 @@ command = ls
108
108
  @file = Tempfile.new(["config", ".ini"])
109
109
  end
110
110
 
111
- it "does not load config if platform is not darwin" do
112
- Invoker.expects(:darwin?).returns(false)
113
- Invoker::Power::Config.expects(:load_config).never
114
- Invoker::Parsers::Config.new(@file.path, 9000)
115
- end
116
-
117
111
  it "does not load config if platform is darwin but there is no power config file" do
118
- Invoker.expects(:darwin?).returns(true)
119
112
  Invoker::Power::Config.expects(:load_config).never
120
113
  Invoker::Parsers::Config.new(@file.path, 9000)
121
114
  end
122
115
 
123
116
  it "loads config if platform is darwin and power config file exists" do
124
- Invoker.expects(:darwin?).returns(true)
125
117
  File.open(Invoker::Power::Config::CONFIG_LOCATION, "w") { |fl| fl.puts "sample" }
126
118
  Invoker::Power::Config.expects(:load_config).once
127
119
  Invoker::Parsers::Config.new(@file.path, 9000)
@@ -14,37 +14,18 @@ describe "Invoker" do
14
14
  end
15
15
 
16
16
  describe "#can_run_balancer?" do
17
- before {
18
- File.exists?(Invoker::Power::Config::CONFIG_LOCATION) &&
19
- File.delete(Invoker::Power::Config::CONFIG_LOCATION)
20
- }
21
-
22
- after {
23
- File.exists?(Invoker::Power::Config::CONFIG_LOCATION) &&
24
- File.delete(Invoker::Power::Config::CONFIG_LOCATION)
25
- }
26
-
27
- it "should return false if setup command was not run on osx" do
28
- Invoker.expects(:ruby_platform).returns("x86_64-darwin12.4.0")
29
- expect(Invoker.can_run_balancer?).to be_false
30
- end
31
-
32
- it "should return false if platform is not osx" do
33
- Invoker.expects(:ruby_platform).returns("i686-linux")
17
+ it "should return false if setup command was not run" do
34
18
  expect(Invoker.can_run_balancer?).to be_false
35
19
  end
36
20
 
37
21
  it "should return true if setup was run properly" do
38
- Invoker.expects(:ruby_platform).returns("x86_64-darwin12.4.0")
39
22
  File.open(Invoker::Power::Config::CONFIG_LOCATION, "w") {|fl|
40
23
  fl.write("hello")
41
24
  }
42
-
43
25
  expect(Invoker.can_run_balancer?).to be_true
44
26
  end
45
27
 
46
28
  it "should not print warning if setup is not run when flag is false" do
47
- Invoker.expects(:ruby_platform).returns("x86_64-darwin12.4.0")
48
29
  Invoker::Logger.expects(:puts).never()
49
30
  Invoker.can_run_balancer?(false)
50
31
  end
@@ -81,4 +62,3 @@ describe "Invoker" do
81
62
  end
82
63
  end
83
64
  end
84
-
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Invoker::Power::Balancer do
4
4
  context "matching domain part of incoming request" do
5
5
  before do
6
- @balancer = Invoker::Power::Balancer.new(mock("connection"))
6
+ @balancer = Invoker::Power::Balancer.new(mock("connection"), "http")
7
7
  end
8
8
 
9
9
  it "should do foo.dev match" do
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+
3
+ describe Invoker::Power::LinuxSetup do
4
+ let(:invoker_setup) { Invoker::Power::LinuxSetup.new }
5
+ describe "should only proceed after user confirmation" do
6
+ it "should create config file with port" do
7
+ invoker_setup.expects(:get_user_confirmation?).returns(true)
8
+ invoker_setup.expects(:install_required_software).returns(true)
9
+ invoker_setup.expects(:install_resolver).returns(true)
10
+ invoker_setup.expects(:install_port_forwarder).returns(true)
11
+ invoker_setup.expects(:restart_services).returns(true)
12
+ invoker_setup.expects(:drop_to_normal_user).returns(true)
13
+
14
+ invoker_setup.setup_invoker
15
+
16
+ config = Invoker::Power::Config.load_config
17
+ expect(config.http_port).not_to be_nil
18
+ expect(config.dns_port).to be_nil
19
+ expect(config.https_port).not_to be_nil
20
+ end
21
+ end
22
+
23
+ describe "configuring dnsmasq and rinetd" do
24
+ it "should create proper config file" do
25
+ invoker_setup.expects(:get_user_confirmation?).returns(true)
26
+ invoker_setup.expects(:install_required_software).returns(true)
27
+ invoker_setup.expects(:restart_services).returns(true)
28
+ invoker_setup.expects(:drop_to_normal_user).returns(true)
29
+
30
+ invoker_setup.setup_invoker
31
+
32
+ config = Invoker::Power::Config.load_config
33
+
34
+ dnsmasq_content = File.read(Invoker::Power::LinuxSetup::RESOLVER_FILE)
35
+ expect(dnsmasq_content.strip).to_not be_empty
36
+ expect(dnsmasq_content).to match(/dev/)
37
+
38
+ rinetd_content = File.read(Invoker::Power::LinuxSetup::RINETD_FILE)
39
+ expect(rinetd_content.strip).to_not be_empty
40
+ expect(rinetd_content.strip).to match(/#{config.https_port}/)
41
+ expect(rinetd_content.strip).to match(/#{config.http_port}/)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,96 @@
1
+ require "spec_helper"
2
+
3
+ describe Invoker::Power::OsxSetup do
4
+ describe "When no setup exists" do
5
+ it "should create a config file with port etc" do
6
+ setup = Invoker::Power::OsxSetup.new
7
+ setup.expects(:install_resolver).returns(true)
8
+ setup.expects(:flush_dns_rules).returns(true)
9
+ setup.expects(:drop_to_normal_user).returns(true)
10
+ setup.expects(:install_firewall).once
11
+
12
+ setup.setup_invoker
13
+
14
+ config = Invoker::Power::Config.load_config
15
+ expect(config.http_port).not_to be_nil
16
+ expect(config.dns_port).not_to be_nil
17
+ expect(config.https_port).not_to be_nil
18
+ end
19
+ end
20
+
21
+ describe "when a setup file exists" do
22
+ it "should throw error about existing file" do
23
+ File.open(Invoker::Power::Config::CONFIG_LOCATION, "w") {|fl|
24
+ fl.write("foo test")
25
+ }
26
+ Invoker::Power::Setup.any_instance.expects(:setup_invoker).never
27
+ Invoker::Power::Setup.install()
28
+ end
29
+ end
30
+
31
+ describe "when pow like setup exists" do
32
+ before {
33
+ File.open(Invoker::Power::OsxSetup::RESOLVER_FILE, "w") {|fl|
34
+ fl.write("hello")
35
+ }
36
+ @setup = Invoker::Power::OsxSetup.new
37
+ }
38
+
39
+ describe "when user selects to overwrite it" do
40
+ it "should run setup normally" do
41
+ @setup.expects(:setup_resolver_file).returns(true)
42
+ @setup.expects(:drop_to_normal_user).returns(true)
43
+ @setup.expects(:install_resolver).returns(true)
44
+ @setup.expects(:flush_dns_rules).returns(true)
45
+ @setup.expects(:install_firewall).once()
46
+
47
+ @setup.setup_invoker
48
+ end
49
+ end
50
+
51
+ describe "when user chose not to overwrite it" do
52
+ it "should abort the setup process" do
53
+ @setup.expects(:setup_resolver_file).returns(false)
54
+
55
+ @setup.expects(:install_resolver).never
56
+ @setup.expects(:flush_dns_rules).never
57
+ @setup.expects(:install_firewall).never
58
+
59
+ @setup.setup_invoker
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "uninstalling firewall rules" do
65
+ it "should uninstall firewall rules and remove all files created by setup" do
66
+ setup = Invoker::Power::OsxSetup.new
67
+
68
+ Invoker::CLI::Question.expects(:agree).returns(true)
69
+ setup.expects(:remove_resolver_file).once
70
+ setup.expects(:unload_firewall_rule).with(true).once
71
+ setup.expects(:flush_dns_rules).once
72
+ Invoker::Power::Config.expects(:delete).once
73
+
74
+ setup.uninstall_invoker
75
+ end
76
+ end
77
+
78
+ describe "setup on fresh osx install" do
79
+ context "when resolver directory does not exist" do
80
+ before do
81
+ @setup = Invoker::Power::OsxSetup.new
82
+ FileUtils.rm_rf(Invoker::Power::OsxSetup::RESOLVER_DIR)
83
+ end
84
+
85
+ it "should create the directory and install" do
86
+ @setup.expects(:setup_resolver_file).returns(true)
87
+ @setup.expects(:drop_to_normal_user).returns(true)
88
+ @setup.expects(:flush_dns_rules).returns(true)
89
+ @setup.expects(:install_firewall).once()
90
+
91
+ @setup.setup_invoker
92
+ expect(Dir.exist?(Invoker::Power::OsxSetup::RESOLVER_DIR)).to be_true
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,104 +1,4 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe "Setup" do
4
- describe "When no setup exists" do
5
- it "should create a config file with port etc" do
6
- setup = Invoker::Power::Setup.new()
7
- setup.expects(:install_resolver).returns(true)
8
- setup.expects(:flush_dns_rules).returns(true)
9
- setup.expects(:drop_to_normal_user).returns(true)
10
- setup.expects(:install_firewall).once()
11
-
12
- setup.setup_invoker
13
-
14
- config = Invoker::Power::Config.load_config()
15
- expect(config.http_port).not_to be_nil
16
- expect(config.dns_port).not_to be_nil
17
- end
18
- end
19
-
20
- describe "setup on non osx systems" do
21
- it "should not run setup" do
22
- Invoker.expects(:ruby_platform).returns("i686-linux")
23
- Invoker::Power::Setup.any_instance.expects(:check_if_setup_can_run?).never()
24
- Invoker::Power::Setup.install
25
- end
26
- end
27
-
28
- describe "when a setup file exists" do
29
- it "should throw error about existing file" do
30
- File.open(Invoker::Power::Config::CONFIG_LOCATION, "w") {|fl|
31
- fl.write("foo test")
32
- }
33
- Invoker::Power::Setup.any_instance.expects(:setup_invoker).never
34
- Invoker::Power::Setup.install()
35
- end
36
- end
37
-
38
- describe "when pow like setup exists" do
39
- before {
40
- File.open(Invoker::Power::Setup::RESOLVER_FILE, "w") {|fl|
41
- fl.write("hello")
42
- }
43
- @setup = Invoker::Power::Setup.new
44
- }
45
-
46
- describe "when user selects to overwrite it" do
47
- it "should run setup normally" do
48
- @setup.expects(:setup_resolver_file).returns(true)
49
- @setup.expects(:drop_to_normal_user).returns(true)
50
- @setup.expects(:install_resolver).returns(true)
51
- @setup.expects(:flush_dns_rules).returns(true)
52
- @setup.expects(:install_firewall).once()
53
-
54
- @setup.setup_invoker
55
- end
56
- end
57
-
58
- describe "when user chose not to overwrite it" do
59
- it "should abort the setup process" do
60
- @setup.expects(:setup_resolver_file).returns(false)
61
-
62
- @setup.expects(:install_resolver).never
63
- @setup.expects(:flush_dns_rules).never
64
- @setup.expects(:install_firewall).never
65
-
66
- @setup.setup_invoker
67
- end
68
- end
69
- end
70
-
71
- describe "uninstalling firewall rules" do
72
- it "should uninstall firewall rules and remove all files created by setup" do
73
- setup = Invoker::Power::Setup.new
74
-
75
- Invoker::CLI::Question.expects(:agree).returns(true)
76
- setup.expects(:remove_resolver_file).once
77
- setup.expects(:unload_firewall_rule).with(true).once
78
- setup.expects(:flush_dns_rules).once
79
- Invoker::Power::Config.expects(:delete).once
80
-
81
- setup.uninstall_invoker
82
- end
83
- end
84
-
85
- describe "setup on fresh osx install" do
86
- context "when resolver directory does not exist" do
87
- before do
88
- @setup = Invoker::Power::Setup.new()
89
- FileUtils.rm_rf(Invoker::Power::Setup::RESOLVER_DIR)
90
- end
91
-
92
- it "should create the directory and install" do
93
- @setup.expects(:setup_resolver_file).returns(true)
94
- @setup.expects(:drop_to_normal_user).returns(true)
95
- @setup.expects(:flush_dns_rules).returns(true)
96
- @setup.expects(:install_firewall).once()
97
-
98
- @setup.setup_invoker()
99
-
100
- expect(Dir.exists?(Invoker::Power::Setup::RESOLVER_DIR)).to be_true
101
- end
102
- end
103
- end
104
4
  end
@@ -7,6 +7,8 @@ end
7
7
 
8
8
  require "invoker"
9
9
  require "invoker/power/power"
10
+ $: << File.join(File.dirname(__FILE__), "support")
11
+ require "mock_setup_file"
10
12
  MM = Invoker::IPC::Message
11
13
 
12
14
  RSpec.configure do |config|
@@ -14,44 +16,16 @@ RSpec.configure do |config|
14
16
  config.run_all_when_everything_filtered = true
15
17
  config.filter_run :focus
16
18
  config.mock_framework = :mocha
19
+ config.include MockSetupFile
17
20
 
18
- config.before(:each) do
19
- @original_verbosity = $VERBOSE
21
+ config.around do |example|
22
+ original_verbosity = $VERBOSE
20
23
  $VERBOSE = nil
21
- @old_config = Invoker::Power::Config::CONFIG_LOCATION
22
- Invoker::Power::Config.const_set(:CONFIG_LOCATION, "/tmp/.invoker/config")
23
- FileUtils.mkdir("/tmp/.invoker") unless Dir.exist?("/tmp/.invoker")
24
-
25
- File.exists?(Invoker::Power::Config::CONFIG_LOCATION) &&
26
- File.delete(Invoker::Power::Config::CONFIG_LOCATION)
27
-
28
- @old_resolver = Invoker::Power::Setup::RESOLVER_FILE
29
- Invoker::Power::Setup.const_set(:RESOLVER_FILE, "/tmp/resolver/invoker-dev")
30
- Invoker::Power::Setup.const_set(:RESOLVER_DIR, "/tmp/resolver")
31
-
32
- unless Dir.exists?(Invoker::Power::Setup::RESOLVER_DIR)
33
- FileUtils.mkdir(Invoker::Power::Setup::RESOLVER_DIR)
34
- end
35
-
36
- File.exists?(Invoker::Power::Setup::RESOLVER_FILE) &&
37
- File.delete(Invoker::Power::Setup::RESOLVER_FILE)
24
+ setup_mocked_config_files
25
+ example.run
26
+ remove_mocked_config_files
27
+ $VERBOSE = original_verbosity
38
28
  end
39
-
40
- config.after(:each) do
41
- File.exists?(Invoker::Power::Config::CONFIG_LOCATION) &&
42
- File.delete(Invoker::Power::Config::CONFIG_LOCATION)
43
-
44
- Invoker::Power::Config.const_set(:CONFIG_LOCATION, @old_config)
45
-
46
- File.exists?(Invoker::Power::Setup::RESOLVER_FILE) &&
47
- File.delete(Invoker::Power::Setup::RESOLVER_FILE)
48
-
49
- FileUtils.rm_rf(Invoker::Power::Setup::RESOLVER_DIR)
50
- Invoker::Power::Setup.const_set(:RESOLVER_FILE, @old_resolver)
51
-
52
- $VERBOSE = @original_verbosity
53
- end
54
-
55
29
  # Run specs in random order to surface order dependencies. If you find an
56
30
  # order dependency and want to debug it, you can fix the order by providing
57
31
  # the seed, which is printed after each run.
@@ -0,0 +1,68 @@
1
+ module MockSetupFile
2
+ def setup_mocked_config_files
3
+ setup_invoker_config
4
+ setup_osx_resolver_path
5
+ setup_linux_resolver_path
6
+ end
7
+
8
+ def remove_mocked_config_files
9
+ restore_invoker_config
10
+ restore_osx_resolver_setup
11
+ restore_linux_resolver_path
12
+ end
13
+
14
+ def safe_remove_file(file_location)
15
+ File.exist?(file_location) &&
16
+ File.delete(file_location)
17
+ end
18
+
19
+ def safe_make_directory(directory)
20
+ FileUtils.mkdir(directory) unless Dir.exist?(directory)
21
+ end
22
+
23
+ private
24
+
25
+ def setup_invoker_config
26
+ @old_config = Invoker::Power::Config::CONFIG_LOCATION
27
+ Invoker::Power::Config.const_set(:CONFIG_LOCATION, "/tmp/.invoker/config")
28
+ safe_make_directory("/tmp/.invoker")
29
+ safe_remove_file(Invoker::Power::Config::CONFIG_LOCATION)
30
+ end
31
+
32
+ def restore_invoker_config
33
+ safe_remove_file(Invoker::Power::Config::CONFIG_LOCATION)
34
+ Invoker::Power::Config.const_set(:CONFIG_LOCATION, @old_config)
35
+ $VERBOSE = @original_verbosity
36
+ end
37
+
38
+ def restore_osx_resolver_setup
39
+ safe_remove_file(Invoker::Power::OsxSetup::RESOLVER_FILE)
40
+ FileUtils.rm_rf(Invoker::Power::OsxSetup::RESOLVER_DIR)
41
+ Invoker::Power::OsxSetup.const_set(:RESOLVER_FILE, @old_osx_resolver)
42
+ end
43
+
44
+ def setup_osx_resolver_path
45
+ @old_osx_resolver = Invoker::Power::OsxSetup::RESOLVER_FILE
46
+ Invoker::Power::OsxSetup.const_set(:RESOLVER_FILE, "/tmp/resolver/invoker-dev")
47
+ Invoker::Power::OsxSetup.const_set(:RESOLVER_DIR, "/tmp/resolver")
48
+
49
+ safe_make_directory(Invoker::Power::OsxSetup::RESOLVER_DIR)
50
+ safe_remove_file(Invoker::Power::OsxSetup::RESOLVER_FILE)
51
+ end
52
+
53
+ def setup_linux_resolver_path
54
+ @old_linux_resolver = Invoker::Power::LinuxSetup::RESOLVER_FILE
55
+ @old_rinetd_config = Invoker::Power::LinuxSetup::RINETD_FILE
56
+ Invoker::Power::LinuxSetup.const_set(:RESOLVER_FILE, "/tmp/dev-tld")
57
+ Invoker::Power::LinuxSetup.const_set(:RINETD_FILE, "/tmp/rinetd.conf")
58
+ safe_remove_file(Invoker::Power::LinuxSetup::RESOLVER_FILE)
59
+ safe_remove_file(Invoker::Power::LinuxSetup::RINETD_FILE)
60
+ end
61
+
62
+ def restore_linux_resolver_path
63
+ safe_remove_file(Invoker::Power::LinuxSetup::RESOLVER_FILE)
64
+ safe_remove_file(Invoker::Power::LinuxSetup::RINETD_FILE)
65
+ Invoker::Power::LinuxSetup.const_set(:RESOLVER_FILE, @old_linux_resolver)
66
+ Invoker::Power::LinuxSetup.const_set(:RINETD_FILE, @old_rinetd_config)
67
+ end
68
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: invoker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hemant Kumar
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-11 00:00:00.000000000 Z
12
+ date: 2014-05-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -219,7 +219,6 @@ files:
219
219
  - lib/invoker/cli/tail_watcher.rb
220
220
  - lib/invoker/command_worker.rb
221
221
  - lib/invoker/commander.rb
222
- - lib/invoker/config.rb
223
222
  - lib/invoker/daemon.rb
224
223
  - lib/invoker/dns_cache.rb
225
224
  - lib/invoker/errors.rb
@@ -251,6 +250,8 @@ files:
251
250
  - lib/invoker/power/power.rb
252
251
  - lib/invoker/power/powerup.rb
253
252
  - lib/invoker/power/setup.rb
253
+ - lib/invoker/power/setup/linux_setup.rb
254
+ - lib/invoker/power/setup/osx_setup.rb
254
255
  - lib/invoker/power/templates/404.html
255
256
  - lib/invoker/power/templates/503.html
256
257
  - lib/invoker/process_manager.rb
@@ -277,10 +278,13 @@ files:
277
278
  - spec/invoker/power/config_spec.rb
278
279
  - spec/invoker/power/http_response_spec.rb
279
280
  - spec/invoker/power/port_finder_spec.rb
281
+ - spec/invoker/power/setup/linux_setup_spec.rb
282
+ - spec/invoker/power/setup/osx_setup_spec.rb
280
283
  - spec/invoker/power/setup_spec.rb
281
284
  - spec/invoker/process_manager_spec.rb
282
285
  - spec/invoker/reactor_spec.rb
283
286
  - spec/spec_helper.rb
287
+ - spec/support/mock_setup_file.rb
284
288
  homepage: http://invoker.codemancers.com
285
289
  licenses:
286
290
  - MIT
@@ -305,27 +309,5 @@ rubygems_version: 2.2.2
305
309
  signing_key:
306
310
  specification_version: 4
307
311
  summary: Something small for Process management
308
- test_files:
309
- - spec/invoker/cli/pinger_spec.rb
310
- - spec/invoker/cli/tail_watcher_spec.rb
311
- - spec/invoker/cli_spec.rb
312
- - spec/invoker/command_worker_spec.rb
313
- - spec/invoker/commander_spec.rb
314
- - spec/invoker/config_spec.rb
315
- - spec/invoker/daemon_spec.rb
316
- - spec/invoker/event/manager_spec.rb
317
- - spec/invoker/invoker_spec.rb
318
- - spec/invoker/ipc/client_handler_spec.rb
319
- - spec/invoker/ipc/dns_check_command_spec.rb
320
- - spec/invoker/ipc/message/list_response_spec.rb
321
- - spec/invoker/ipc/message_spec.rb
322
- - spec/invoker/ipc/unix_client_spec.rb
323
- - spec/invoker/power/balancer_spec.rb
324
- - spec/invoker/power/config_spec.rb
325
- - spec/invoker/power/http_response_spec.rb
326
- - spec/invoker/power/port_finder_spec.rb
327
- - spec/invoker/power/setup_spec.rb
328
- - spec/invoker/process_manager_spec.rb
329
- - spec/invoker/reactor_spec.rb
330
- - spec/spec_helper.rb
312
+ test_files: []
331
313
  has_rdoc:
@@ -1,5 +0,0 @@
1
- module Invoker
2
- module Config
3
-
4
- end
5
- end