explorer 0.0.4 → 0.0.5

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: 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