explorer 0.0.1 → 0.0.2

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: ecdc58b1c28dcdbd33d92cfab008eb4252df0fb8
4
- data.tar.gz: 7e0f277198bb44695818fc849a4f11480767d5b1
3
+ metadata.gz: 92c4c5434dfa27aea21de62e797f79e5634aee95
4
+ data.tar.gz: 332c6ce3352491289eaf6c3199f599e9216395b8
5
5
  SHA512:
6
- metadata.gz: 3aa239b18db10c9c8573b7b6116f5da84f6647ee595a8a08a9950c01d7b7e36e91d0cb729f4d9713a3c2cde9921dcdeec5d6ab87f394cc177810205e3c4732e1
7
- data.tar.gz: 552fdfb5179d368fe5ba55a4c905da3ed728b659621a3c5ac9fcebabf6e00bd722154c89b4640b9124430ba94997001555ed2532af3f1800f42a6f3a7674f184
6
+ metadata.gz: d574b77ff7efdb07ba7821823fc1c96152459812a9c0f4ef111bc9ffa1b1c9eb5d6c0b6a342220f05a82824d51a0390f4346cf4a12a4e5e179f07d33cf23cdf1
7
+ data.tar.gz: 98d3806a19b602d463d44cbe8652194664b84923bf0b1220ab3378837230131ceea14e7dac30645547730e294237db04a2201950960f400ccf34c45a2656cc09
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Explorer
2
2
 
3
- TODO: Write a gem description
3
+ Explorer is a replacement for Pow! written in Ruby.
4
+
5
+ [![Dependency Status](https://gemnasium.com/Darksecond/explorer.svg)](https://gemnasium.com/Darksecond/explorer)
4
6
 
5
7
  ## Installation
6
8
 
data/bin/explore CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'explorer'
4
4
 
5
- Explorer::CLI.start(ARGV)
5
+ Explorer::CLI::CLI.start(ARGV)
data/explorer.gemspec CHANGED
@@ -26,4 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency 'thor', '~> 0.19'
27
27
  spec.add_dependency 'celluloid', '~> 0.16'
28
28
  spec.add_dependency 'celluloid-io', '~> 0.16'
29
+ spec.add_dependency 'dotenv', '~> 1.0'
30
+ spec.add_dependency 'rainbow', '~> 2.0'
31
+ spec.add_dependency 'formatador', '~> 0.2'
29
32
  end
data/lib/explorer/cli.rb CHANGED
@@ -1,50 +1,30 @@
1
1
  require 'thor'
2
+ require 'explorer/cli/proxy'
3
+ require 'explorer/cli/process'
2
4
 
3
5
  module Explorer
4
- class CLI < Thor
5
- desc "version", "Print version of explorer"
6
- def version
7
- puts Explorer::VERSION
8
- end
9
- map %w(-v --version) => :version
10
-
11
- desc "start CONFIG", 'Start explorer'
12
- def start(file)
13
- servers = Servers.new hostmap: {'test.dev' => {host: 'localhost', port: 8080}}
14
- servers.log_watcher.add(STDOUT)
15
- servers.run
16
- end
17
-
18
- desc 'map-list', 'List hostmapping'
19
- def map_list
20
- ipc = IPCClient.new
21
- map = ipc.hostmap_list
22
- puts "-------------------------------------------------------"
23
- puts "| MAP | HOST | PORT |"
24
- map.each do |k,v|
25
- puts "| #{k.rjust(15)} | #{v['host'].rjust(15)} | #{v['port'].to_s.rjust(15)} |"
6
+ module CLI
7
+ # TODO: Rename
8
+ class CLI < Thor
9
+ desc "version", "Print version of explorer"
10
+ def version
11
+ puts Explorer::VERSION
26
12
  end
27
- puts "-------------------------------------------------------"
28
- end
13
+ map %w(-v --version) => :version
29
14
 
30
- desc 'map-add DOMAIN HOST PORT', 'Add to mapping'
31
- def map_add(domain, host, port)
32
- ipc = IPCClient.new
33
- ipc.hostmap_add(domain, host, port)
34
- puts "Added #{domain} to hostmap"
35
- end
15
+ desc 'proxy SUBCOMMAND ...ARGS', 'manage proxy'
16
+ subcommand 'proxy', Proxy
36
17
 
37
- desc 'tail', 'Tail log'
38
- def tail
39
- ipc = IPCClient.new
40
- ipc.tail
41
- end
18
+ desc 'process SUBCOMMAND ...ARGS', 'manage processes'
19
+ subcommand 'process', Process
20
+
21
+ desc "boot [CONFIG]", 'Start explorer'
22
+ def boot(config=nil)
23
+ servers = Servers.new hostmap: {'test.dev' => {host: 'localhost', port: 8080}}
24
+ servers.log_watcher.add(STDOUT)
25
+ servers.run
26
+ end
42
27
 
43
- desc 'cmd-add LABEL CMD', 'Add command'
44
- option :dir
45
- def cmd_add(label, cmd)
46
- ipc = IPCClient.new
47
- ipc.cmd_add(label, cmd, options[:dir])
48
28
  end
49
29
  end
50
30
  end
@@ -0,0 +1,89 @@
1
+ require 'rainbow'
2
+ require 'formatador'
3
+
4
+ module Explorer
5
+ module CLI
6
+ class Process < Thor
7
+ desc 'tail', 'Tail log'
8
+ def tail
9
+ Celluloid.logger = nil # Silence celluloid
10
+
11
+ ipc = IPCClient.new
12
+ ipc.tail
13
+ rescue Errno::ENOENT
14
+ puts Rainbow('Explore is not running').color(:red).bright
15
+ end
16
+
17
+ desc 'add LABEL CMD (--dir=DIR)', 'Add command'
18
+ option :dir
19
+ def add(label, cmd)
20
+ Celluloid.logger = nil # Silence celluloid
21
+
22
+ ipc = IPCClient.new
23
+ ipc.cmd_add(label, cmd, options[:dir])
24
+ puts Rainbow("Added #{label}").color(:green).bright
25
+ rescue Errno::ENOENT
26
+ puts Rainbow('Explore is not running').color(:red).bright
27
+ end
28
+
29
+ desc 'start LABEL', 'Start process'
30
+ def start(label)
31
+ Celluloid.logger = nil # Silence celluloid
32
+
33
+ ipc = IPCClient.new
34
+ ipc.cmd_start(label)
35
+ puts Rainbow("Started #{label}").color(:green).bright
36
+ rescue Errno::ENOENT
37
+ puts Rainbow('Explore is not running').color(:red).bright
38
+ end
39
+
40
+ desc 'stop LABEL', 'Stop process'
41
+ def stop(label)
42
+ Celluloid.logger = nil # Silence celluloid
43
+
44
+ ipc = IPCClient.new
45
+ ipc.cmd_stop(label)
46
+ puts Rainbow("Stopped #{label}").color(:green).bright
47
+ rescue Errno::ENOENT
48
+ puts Rainbow('Explore is not running').color(:red).bright
49
+ end
50
+
51
+ desc 'remove LABEL', 'Remove process'
52
+ def remove(label)
53
+ Celluloid.logger = nil # Silence celluloid
54
+
55
+ ipc = IPCClient.new
56
+ ipc.cmd_remove(label)
57
+ puts Rainbow("Removed #{label}").color(:green).bright
58
+ rescue Errno::ENOENT
59
+ puts Rainbow('Explore is not running').color(:red).bright
60
+ end
61
+
62
+ desc 'list', 'list processes'
63
+ def list
64
+ Celluloid.logger = nil # Silence celluloid
65
+
66
+ ipc = IPCClient.new
67
+ list = ipc.cmd_list
68
+ data = list.map do |p|
69
+ color = if p['state'] == 'stopped'
70
+ 'red'
71
+ else
72
+ 'green'
73
+ end
74
+ {
75
+ label: "[#{color}]#{p['label']}[/]",
76
+ command: "[#{color}]#{p['cmd']}[/]",
77
+ 'working directory' => "[#{color}]#{p['dir']}[/]",
78
+ 'PID' => "[#{color}]#{p['pid']}[/]",
79
+ 'exit code' => "[#{color}]#{p['status']}[/]",
80
+ 'status' => "[#{color}]#{p['state']}[/]",
81
+ }
82
+ end
83
+ Formatador.display_compact_table(data, [:label, :command, 'PID', 'exit code', 'status', 'working directory'])
84
+ rescue Errno::ENOENT
85
+ puts Rainbow('Explore is not running').color(:red).bright
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,47 @@
1
+ require 'rainbow'
2
+ require 'formatador'
3
+
4
+ module Explorer
5
+ module CLI
6
+ class Proxy < Thor
7
+ desc 'list', 'List proxy map'
8
+ def list
9
+ Celluloid.logger = nil # Silence celluloid
10
+
11
+ ipc = IPCClient.new
12
+ data = ipc.hostmap_list.map do |k, v|
13
+ {
14
+ domain: "[yellow]#{k}[/]",
15
+ host: "[yellow]#{v['host']}[/]",
16
+ port: "[yellow]#{v['port']}[/]",
17
+ }
18
+ end
19
+ Formatador.display_compact_table(data, [:domain, :host, :port])
20
+ rescue Errno::ENOENT
21
+ puts Rainbow('Explore is not running').color(:red).bright
22
+ end
23
+
24
+ desc 'add DOMAIN HOST PORT', 'Add domain to proxy'
25
+ def add(domain, host, port)
26
+ Celluloid.logger = nil # Silence celluloid
27
+
28
+ ipc = IPCClient.new
29
+ ipc.hostmap_add(domain, host, port)
30
+ puts "Added #{domain} to proxy"
31
+ rescue Errno::ENOENT
32
+ puts Rainbow('Explore is not running').color(:red).bright
33
+ end
34
+
35
+ desc 'remove DOMAIN', 'remove domain from proxy'
36
+ def remove(domain)
37
+ Celluloid.logger = nil # Silence celluloid
38
+
39
+ ipc = IPCClient.new
40
+ ipc.hostmap_remove(domain)
41
+ puts "Removed #{domain} from proxy"
42
+ rescue Errno::ENOENT
43
+ puts Rainbow('Explore is not running').color(:red).bright
44
+ end
45
+ end
46
+ end
47
+ end
@@ -29,9 +29,17 @@ module Explorer
29
29
  @socket.puts msg.to_json
30
30
  end
31
31
 
32
+ def hostmap_remove domain
33
+ msg = {
34
+ command: 'map-remove',
35
+ map: domain
36
+ }
37
+ @socket.puts msg.to_json
38
+ end
39
+
32
40
  def tail(io = STDOUT)
33
41
  msg = {
34
- command: 'tail'
42
+ command: 'cmd-tail'
35
43
  }
36
44
  @socket.puts msg.to_json
37
45
 
@@ -51,6 +59,38 @@ module Explorer
51
59
  @socket.puts msg.to_json
52
60
  end
53
61
 
62
+ def cmd_start(label)
63
+ msg = {
64
+ command: 'cmd-start',
65
+ label: label,
66
+ }
67
+ @socket.puts msg.to_json
68
+ end
69
+
70
+ def cmd_stop(label)
71
+ msg = {
72
+ command: 'cmd-stop',
73
+ label: label,
74
+ }
75
+ @socket.puts msg.to_json
76
+ end
77
+
78
+ def cmd_remove(label)
79
+ msg = {
80
+ command: 'cmd-remove',
81
+ label: label,
82
+ }
83
+ @socket.puts msg.to_json
84
+ end
85
+
86
+ def cmd_list
87
+ msg = {
88
+ command: 'cmd-list'
89
+ }
90
+ @socket.puts msg.to_json
91
+ JSON.parse @socket.readline
92
+ end
93
+
54
94
  def shutdown
55
95
  @socket.close if @socket
56
96
  end
@@ -5,15 +5,16 @@ module Explorer
5
5
  finalizer :shutdown
6
6
 
7
7
  attr_reader :label, :command, :working_dir, :state, :status
8
- attr_reader :pid, :pgid, :pipe, :log_watcher
8
+ attr_reader :pid, :pgid, :pipe, :log_watcher, :env
9
9
 
10
10
  # Log watcher should implement a 'log' method which accepts a label and a line of text
11
11
  # Log watcher should also be thread-safe or an actor
12
- def initialize(label, command, working_dir: ENV['PWD'], log_watcher: nil)
12
+ def initialize(label, command, working_dir: ENV['PWD'], log_watcher: nil, env: {})
13
13
  @label = label
14
14
  @command = command
15
15
  @working_dir = working_dir
16
16
  @log_watcher = log_watcher
17
+ @env = env
17
18
  @state = :stopped
18
19
  @status = nil
19
20
  end
@@ -95,7 +96,6 @@ module Explorer
95
96
  end
96
97
 
97
98
  def spawn_process(label, command, working_dir: ENV['PWD'], pipe: :out)
98
- env = {}
99
99
  options = {
100
100
  chdir: working_dir,
101
101
  in: :close,
@@ -1,3 +1,5 @@
1
+ require 'dotenv'
2
+
1
3
  module Explorer
2
4
  class ProcessManager
3
5
  def initialize log_watcher = nil
@@ -12,8 +14,8 @@ module Explorer
12
14
  end
13
15
 
14
16
  def add(label, command, working_dir: ENV['PWD'])
15
- #TODO $PORT replacement? (or somewhere else, perhaps)
16
- @processes[label] = Process.new(label, command, working_dir: working_dir, log_watcher: @log_watcher)
17
+ env = load_env(working_dir)
18
+ @processes[label] = Process.new(label, command, working_dir: working_dir, log_watcher: @log_watcher, env: env)
17
19
  end
18
20
 
19
21
  def remove(label)
@@ -53,5 +55,13 @@ module Explorer
53
55
  def labels
54
56
  @processes.keys
55
57
  end
58
+
59
+ private
60
+
61
+ def load_env(directory = ENV['PWD'])
62
+ path = File.join(directory, '.env')
63
+ return {} unless File.exist?(path)
64
+ Dotenv::Environment.new(path)
65
+ end
56
66
  end
57
67
  end
@@ -34,11 +34,29 @@ module Explorer
34
34
  socket.puts @servers.hostmap.to_json
35
35
  when 'map-add'
36
36
  @servers.hostmap[json['map']] = { host: json['host'], port: json['port'].to_i }
37
- when 'tail'
37
+ when 'map-remove'
38
+ @servers.hostmap.delete json['map']
39
+ when 'cmd-tail'
38
40
  @servers.log_watcher.add(socket)
39
41
  when 'cmd-add'
40
42
  @servers.process_manager.add(json['label'], json['cmd'], working_dir: json['dir'] || ENV['PWD'])
41
- @servers.process_manager.start(json['label']) #TODO Refactor out?
43
+ when 'cmd-start'
44
+ @servers.process_manager.start(json['label'])
45
+ when 'cmd-stop'
46
+ @servers.process_manager.stop(json['label'])
47
+ when 'cmd-remove'
48
+ @servers.process_manager.remove(json['label'])
49
+ when 'cmd-list'
50
+ socket.puts @servers.process_manager.processes.map { |p|
51
+ {
52
+ label: p.label,
53
+ cmd: p.command,
54
+ dir: p.working_dir,
55
+ state: p.state,
56
+ pid: p.pid,
57
+ status: p.status.nil? ? nil : p.status.to_i,
58
+ }
59
+ }.to_json
42
60
  end
43
61
  end
44
62
  rescue EOFError, JSON::ParserError
@@ -1,3 +1,3 @@
1
1
  module Explorer
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: explorer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Peters
@@ -108,6 +108,48 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.16'
111
+ - !ruby/object:Gem::Dependency
112
+ name: dotenv
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rainbow
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '2.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '2.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: formatador
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.2'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.2'
111
153
  description: A pow! replacement written in ruby.
112
154
  email:
113
155
  - mail@darksecond.nl
@@ -128,6 +170,8 @@ files:
128
170
  - lib/celluloid/io/pty.rb
129
171
  - lib/explorer.rb
130
172
  - lib/explorer/cli.rb
173
+ - lib/explorer/cli/process.rb
174
+ - lib/explorer/cli/proxy.rb
131
175
  - lib/explorer/ipc_client.rb
132
176
  - lib/explorer/log_watcher.rb
133
177
  - lib/explorer/process.rb