explorer 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 98c521d0a44b160340aada8309f8dd0d477a5ed1
4
- data.tar.gz: 914098ac5bf5a11069543362fa6784cbbb69a283
3
+ metadata.gz: 91e8f458b57b8c4eb97ffeb015e48760ebaa567f
4
+ data.tar.gz: f8f840dd80dab06d3e116b0dc7a3f4085f2f06a7
5
5
  SHA512:
6
- metadata.gz: ea0b143c3fd4db514d9151bdaa3fdf79020169cdd1716c31c518d9ffcd7a77f1dea2f791136dbe5de8e5a50c4afe36b8a54e9df648eceb751dfbc5018888d12a
7
- data.tar.gz: 803f6d1d50a28a59fef4e0d485ed7ea7554561db0d54210fdacd2d2a6f8bd6e8d33e22299f8c63afe0ef59ea930444ebf6d4b217d0498d8b3e947b4727d730fd
6
+ metadata.gz: caa9f3faae42f352422074dac92c0e3c024a157704814aa1678d7ac8b422f4ef4aaac5763009ea585ec0441806fa88f7176c55504da2520733c69d23d710950d
7
+ data.tar.gz: 9eadcee57798f0ea63fbcc62cce85646c02b49ac0ac5eb1d7d067b4dcbb1e666edff5301a92af5126a7e2f7af996f7926ac5b81fa855bb17e61567a647bbdde7
@@ -11,10 +11,30 @@ require 'explorer/ipc_client'
11
11
  require 'explorer/process'
12
12
  require 'explorer/process_manager'
13
13
  require 'explorer/log_watcher'
14
+ require 'explorer/hostmap'
14
15
  require 'explorer/setup'
15
16
 
16
17
  module Explorer
17
18
  DATADIR = File.expand_path(File.join(File.dirname(__FILE__), '..', 'data'))
19
+ CONFIGDIR = File.join(Dir.home, '.explorer')
20
+
21
+ def self.hostmap
22
+ @hostmap ||= Hostmap.new
23
+ end
24
+
25
+ def self.process_manager
26
+ @process_manager ||= ProcessManager.new
27
+ end
28
+
29
+ def self.log_watcher
30
+ @log_watcher ||= LogWatcher.new
31
+ end
32
+
33
+ def self.terminate
34
+ @hostmap.terminate if @hostmap
35
+ @log_watcher.terminate if @log_watcher
36
+ @process_manager.terminate if @process_manager
37
+ end
18
38
 
19
39
  def self.without_bundler
20
40
  if defined?(Bundler)
@@ -22,10 +22,10 @@ module Explorer
22
22
  desc 'setup SUBCOMMAND ...ARGS', 'manage explorer setup'
23
23
  subcommand 'setup', Setup
24
24
 
25
- desc "boot [CONFIG]", 'Start explorer'
26
- def boot(config=nil)
27
- servers = Servers.new hostmap: {'test.dev' => {host: 'localhost', port: 8080}}
28
- servers.log_watcher.add(STDOUT)
25
+ desc "boot", 'Start explorer'
26
+ def boot
27
+ servers = Servers.new
28
+ Explorer.log_watcher.add(STDOUT)
29
29
  servers.run
30
30
  end
31
31
 
@@ -0,0 +1,44 @@
1
+ require 'yaml'
2
+
3
+ module Explorer
4
+ class Hostmap
5
+ include Celluloid
6
+
7
+ attr_reader :mappings
8
+
9
+ def initialize
10
+ @mappings = {}
11
+ end
12
+
13
+ def add domain, host, port
14
+ @mappings[domain] = { host: host, port: port }
15
+ end
16
+
17
+ def remove domain
18
+ @mappings.delete domain
19
+ end
20
+
21
+ def resolve domain
22
+ domain = domain.gsub(/\d+.\d+.\d+.\d+.xip.io/, 'dev') #Support xip.io
23
+ parts = domain.split '.'
24
+ map = nil
25
+ while !parts.empty? && map.nil? do
26
+ map = @mappings[parts.join('.')]
27
+ parts.shift
28
+ end
29
+ map
30
+ end
31
+
32
+ def save file
33
+ Dir.mkdir File.dirname(file) unless Dir.exist?(File.dirname(file))
34
+ File.write file, YAML.dump(mappings)
35
+ end
36
+
37
+ def load file
38
+ return unless File.exist? file
39
+
40
+ yaml = YAML.load_file file
41
+ @mappings = yaml
42
+ end
43
+ end
44
+ end
@@ -30,8 +30,26 @@ module Explorer
30
30
  end
31
31
  end
32
32
 
33
+ def logger(label='system')
34
+ @logger ||= ::Logger.new(LogDevice.new(self, label))
35
+ end
36
+
33
37
  private
34
38
 
39
+ class LogDevice
40
+ def initialize(watcher, label='system')
41
+ @watcher = watcher
42
+ @label = label
43
+ end
44
+
45
+ def close
46
+ end
47
+
48
+ def write(data)
49
+ @watcher.log(@label, data)
50
+ end
51
+ end
52
+
35
53
  def next_color
36
54
  color = COLORS.shift
37
55
  COLORS.push color
@@ -12,7 +12,7 @@ module Explorer
12
12
  def initialize(label, command, working_dir: ENV['PWD'], log_watcher: nil, env: {})
13
13
  @label = label
14
14
  @command = command
15
- @working_dir = working_dir
15
+ @working_dir = File.expand_path(working_dir)
16
16
  @log_watcher = log_watcher
17
17
  @env = env
18
18
  @state = :stopped
@@ -1,9 +1,10 @@
1
1
  require 'dotenv'
2
+ require 'yaml'
2
3
 
3
4
  module Explorer
4
5
  class ProcessManager
5
- def initialize log_watcher = nil
6
- @log_watcher = log_watcher
6
+ def initialize options={}
7
+ @log_watcher = options.fetch(:log_watcher) { Explorer.log_watcher }
7
8
  @processes = {}
8
9
  end
9
10
 
@@ -56,10 +57,30 @@ module Explorer
56
57
  @processes.keys
57
58
  end
58
59
 
60
+ def load file
61
+ return unless File.exist? file
62
+
63
+ yaml = YAML.load_file file
64
+ yaml.each do |cfg|
65
+ add(cfg[:label], cfg[:command], working_dir: cfg[:working_dir])
66
+ end
67
+ end
68
+
69
+ def save file
70
+ Dir.mkdir File.dirname(file) unless Dir.exist?(File.dirname(file))
71
+ File.write file, YAML.dump(processes.map do |p|
72
+ {
73
+ label: p.label,
74
+ command: p.command,
75
+ working_dir: p.working_dir
76
+ }
77
+ end)
78
+ end
79
+
59
80
  private
60
81
 
61
82
  def load_env(directory = ENV['PWD'])
62
- path = File.join(directory, '.env')
83
+ path = File.expand_path File.join(directory, '.env')
63
84
  return {} unless File.exist?(path)
64
85
  Dotenv::Environment.new(path)
65
86
  end
@@ -27,6 +27,8 @@ module Explorer
27
27
  end
28
28
  rescue Errno::ECONNREFUSED
29
29
  reel_request.respond 504, 'Could not connect to upstream server'
30
+ rescue Net::ReadTimeout
31
+ reel_request.respond 599, 'Upstream timed out'
30
32
  end
31
33
 
32
34
  private
@@ -3,7 +3,7 @@ require 'rubydns'
3
3
  module Explorer
4
4
  module Server
5
5
  class DNS < RubyDNS::Server
6
- def initialize(port = 23400)
6
+ def initialize(port)
7
7
  super listen: interfaces(port)
8
8
  async.run
9
9
  end
@@ -3,8 +3,8 @@ require 'reel'
3
3
  module Explorer
4
4
  module Server
5
5
  class HTTP < Reel::Server::HTTP
6
- def initialize(port = 23401, map={})
7
- @map = map
6
+ def initialize(port, options={})
7
+ @map = options.fetch(:hostmap) { Explorer.hostmap }
8
8
 
9
9
  super '0.0.0.0', port, {}, &method(:on_connection)
10
10
  end
@@ -16,7 +16,7 @@ module Explorer
16
16
  end
17
17
 
18
18
  def handle_request(request)
19
- map = @map[request.headers['Host']]
19
+ map = @map.resolve(request.headers['Host'])
20
20
  if map
21
21
  Proxy.new(map[:host], map[:port]).handle(request)
22
22
  else
@@ -3,8 +3,8 @@ require 'reel'
3
3
  module Explorer
4
4
  module Server
5
5
  class HTTPS < Reel::Server::HTTPS
6
- def initialize(port = 23402, map={})
7
- @map = map
6
+ def initialize(port, options={})
7
+ @map = options.fetch(:hostmap) { Explorer.hostmap }
8
8
 
9
9
  options = {
10
10
  cert: File.read(File.join(Explorer::DATADIR, 'server.crt')),
@@ -20,11 +20,11 @@ module Explorer
20
20
  end
21
21
 
22
22
  def handle_request(request)
23
- map = @map[request.headers['Host']]
23
+ map = @map.resolve(request.headers['Host'])
24
24
  if map
25
25
  Proxy.new(map[:host], map[:port]).handle(request)
26
26
  else
27
- request.respond 404, "Map not found (#{request.headers['Host']}) (#{@map.inspect})"
27
+ request.respond 404, "Map not found (#{request.headers['Host']})"
28
28
  end
29
29
 
30
30
  end
@@ -8,10 +8,12 @@ module Explorer
8
8
  finalizer :shutdown
9
9
  attr_reader :socket_path, :server
10
10
 
11
- def initialize(socket_path = '/tmp/explorer_ipc', servers)
11
+ def initialize(socket_path, options={})
12
12
  @socket_path = socket_path
13
13
  @server = UNIXServer.new(socket_path)
14
- @servers = servers
14
+ @hostmap = options.fetch(:hostmap) { Explorer.hostmap }
15
+ @log_watcher = options.fetch(:log_watcher) { Explorer.log_watcher }
16
+ @process_manager = options.fetch(:process_manager) { Explorer.process_manager }
15
17
  async.run
16
18
  end
17
19
 
@@ -31,23 +33,29 @@ module Explorer
31
33
  json = JSON.parse socket.readline
32
34
  case json['command']
33
35
  when 'map-list'
34
- socket.puts @servers.hostmap.to_json
36
+ socket.puts @hostmap.mappings.to_json
35
37
  when 'map-add'
36
- @servers.hostmap[json['map']] = { host: json['host'], port: json['port'].to_i }
38
+ @hostmap.add json['map'], json['host'], json['port'].to_i
39
+ @hostmap.save File.join(Explorer::CONFIGDIR, 'hostmap.yaml') # TODO: Refactor filename
37
40
  when 'map-remove'
38
- @servers.hostmap.delete json['map']
41
+ @hostmap.remove json['map']
42
+ @hostmap.save File.join(Explorer::CONFIGDIR, 'hostmap.yaml')
39
43
  when 'cmd-tail'
40
- @servers.log_watcher.add(socket)
44
+ @log_watcher.add(socket)
41
45
  when 'cmd-add'
42
- @servers.process_manager.add(json['label'], json['cmd'], working_dir: json['dir'] || ENV['PWD'])
46
+ @process_manager.add(json['label'], json['cmd'], working_dir: json['dir'] || ENV['PWD'])
47
+ @process_manager.save File.join(Explorer::CONFIGDIR, 'process.yaml')
43
48
  when 'cmd-start'
44
- @servers.process_manager.start(json['label'])
49
+ @process_manager.start(json['label'])
50
+ @process_manager.save File.join(Explorer::CONFIGDIR, 'process.yaml')
45
51
  when 'cmd-stop'
46
- @servers.process_manager.stop(json['label'])
52
+ @process_manager.stop(json['label'])
53
+ @process_manager.save File.join(Explorer::CONFIGDIR, 'process.yaml')
47
54
  when 'cmd-remove'
48
- @servers.process_manager.remove(json['label'])
55
+ @process_manager.remove(json['label'])
56
+ @process_manager.save File.join(Explorer::CONFIGDIR, 'process.yaml')
49
57
  when 'cmd-list'
50
- socket.puts @servers.process_manager.processes.map { |p|
58
+ socket.puts @process_manager.processes.map { |p|
51
59
  {
52
60
  label: p.label,
53
61
  cmd: p.command,
@@ -1,19 +1,12 @@
1
1
  require 'celluloid'
2
2
 
3
3
  module Explorer
4
- # TODO: Hostmap should be it's own actor; immutable; or thread-safe
5
4
  class Servers
6
- attr_reader :dns_port, :http_port, :https_port, :ipc_file
7
- attr_reader :hostmap, :process_manager, :log_watcher
8
-
9
- def initialize dns_port: 23400, http_port: 23401, https_port: 23402, hostmap: {}, ipc_file: '/tmp/explorer_ipc'
10
- @dns_port = dns_port
11
- @http_port = http_port
12
- @https_port = https_port
13
- @ipc_file = ipc_file
14
- @hostmap = hostmap
15
- @log_watcher = LogWatcher.new
16
- @process_manager = ProcessManager.new log_watcher
5
+ def initialize options={}
6
+ @dns_port = options.fetch(:dns_port) { 23400 }
7
+ @http_port = options.fetch(:http_port) { 23401 }
8
+ @https_port = options.fetch(:https_port) { 23402 }
9
+ @ipc_file = options.fetch(:ipc_file) { '/tmp/explorer_ipc' }
17
10
  end
18
11
 
19
12
  def run
@@ -24,24 +17,33 @@ module Explorer
24
17
  # Start servers
25
18
  run!
26
19
 
20
+ # Load configuration
21
+ load
22
+
27
23
  IO.select([read]) # Wait for trap
28
24
 
29
25
  # Cleanup
30
26
  terminate
31
27
  end
32
28
 
29
+ def load
30
+ Explorer.hostmap.load File.join(Explorer::CONFIGDIR, 'hostmap.yaml')
31
+ Explorer.process_manager.load File.join(Explorer::CONFIGDIR, 'process.yaml')
32
+ end
33
+
34
+ # Do I need this?
33
35
  def terminate
34
36
  @group.terminate if @group
35
- @process_manager.terminate if @process_manager
36
- @log_watcher.terminate if @log_watcher
37
+ Explorer.terminate
37
38
  end
38
39
 
39
40
  def run!
41
+ Celluloid.logger = Explorer.log_watcher.logger
40
42
  @group = Celluloid::SupervisionGroup.new do |group|
41
- group.supervise_as :dns, Server::DNS, dns_port
42
- group.supervise_as :http, Server::HTTP, http_port, hostmap
43
- group.supervise_as :https, Server::HTTPS, https_port, hostmap
44
- group.supervise_as :ipc, Server::IPC, ipc_file, self
43
+ group.supervise_as :dns, Server::DNS, @dns_port
44
+ group.supervise_as :http, Server::HTTP, @http_port
45
+ group.supervise_as :https, Server::HTTPS, @https_port
46
+ group.supervise_as :ipc, Server::IPC, @ipc_file
45
47
  end
46
48
  end
47
49
  end
@@ -1,3 +1,3 @@
1
1
  module Explorer
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: explorer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Peters
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-11 00:00:00.000000000 Z
11
+ date: 2015-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -175,6 +175,7 @@ files:
175
175
  - lib/explorer/cli/process.rb
176
176
  - lib/explorer/cli/proxy.rb
177
177
  - lib/explorer/cli/setup.rb
178
+ - lib/explorer/hostmap.rb
178
179
  - lib/explorer/ipc_client.rb
179
180
  - lib/explorer/log_watcher.rb
180
181
  - lib/explorer/process.rb