easy-serve 0.3 → 0.4

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: affa8e536ee5d6c7d9b703a45267bcc7fec96535
4
- data.tar.gz: d389e400e0e5408ac08400cfd61661befeaaf514
3
+ metadata.gz: fa7e317b0835fcccb71074755f7c440a36eb97c5
4
+ data.tar.gz: f1473351a5081398d0c1a8dc4fe424555cbe7a8b
5
5
  SHA512:
6
- metadata.gz: 5f552e68ca9612ebaacbef58ce31395b7da8121a6753855aebb3bfac58bf07fb435f45dc0f4184395a02d3c9e8590249785307b79f603472e29adaa4f97b0f6f
7
- data.tar.gz: 07aedd1e1b46b0ce875e5dee6cc37220e8e90ca929ebf6bff445a7e6f234733ad07b81416a9b89d14dd04be703bc728599ac18d73eef1762bdc0f00196cf44d1
6
+ metadata.gz: 3f5ee396c21115e4d691c15409aa47f07ca9947a82753e33db9663f21e58ba0930f53541a193095b9705a44d14d96018ad6c03c38a187c407379d90196c7c1ac
7
+ data.tar.gz: b4027e51407e2070ec4039f70fda510cc5b8a22e5aae5396de86c360e2c2366840f9436bd84d313fc0b2ead5df016c4ff7cd4c83276d719512da868a82a64123
@@ -0,0 +1,55 @@
1
+ require 'easy-serve/remote'
2
+
3
+ addr_there = ARGV.shift
4
+
5
+ unless addr_there
6
+ abort <<-END
7
+
8
+ Usage: #$0 addr_there
9
+
10
+ The 'addr_there' is the remote address on which client code will run.
11
+ It must be a destination accepted by ssh, optionally including a user name:
12
+
13
+ [user@]hostname
14
+
15
+ The 'hostname' must be a valid hostname (not just an ssh alias), since it
16
+ will be used for the drb connection as well.
17
+
18
+ END
19
+ end
20
+
21
+ EasyServe.start do |ez|
22
+ log = ez.log
23
+ log.level = Logger::INFO
24
+ log.formatter = nil if $VERBOSE
25
+
26
+ ez.start_servers do
27
+ ez.server "simple-server", :tcp, nil, 0 do |svr|
28
+ Thread.new do
29
+ loop do
30
+ Thread.new(svr.accept) do |conn|
31
+ log.info "accepted connection from #{conn.inspect}"
32
+ conn.write "hello from #{log.progname}"
33
+ log.info "wrote greeting"
34
+ conn.close_write
35
+ log.info "trying to read from #{conn.inspect}"
36
+ log.info "received: #{conn.read}"
37
+ conn.close
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ ez.remote "simple-server", host: addr_there do |conn|
45
+ # this block runs locally, but calls methods on the remote using drb
46
+ log.progname = "druby remote on #{addr_there}"
47
+ log.info "trying to read from #{conn.inspect}"
48
+ log.info "received: #{conn.read}"
49
+ # note: conn is drb proxy to real conn on remote host, so after the
50
+ # string is read from the socket in the remote, it is then serialized
51
+ # by drb back to this (local) process. Don't do this in production!
52
+ conn.write "hello from #{log.progname}"
53
+ conn.close
54
+ end
55
+ end
@@ -0,0 +1,56 @@
1
+ require 'easy-serve/remote'
2
+
3
+ addr_there = ARGV.shift
4
+
5
+ unless addr_there
6
+ abort <<-END
7
+
8
+ Usage: #$0 addr_there
9
+
10
+ The 'addr_there' is the remote address on which client code will run.
11
+ It must be a destination accepted by ssh, optionally including a user name:
12
+
13
+ [user@]hostname
14
+
15
+ The 'hostname' may by any valid hostname or ssh alias.
16
+
17
+ END
18
+ end
19
+
20
+ EasyServe.start do |ez|
21
+ log = ez.log
22
+ log.level = Logger::INFO
23
+ log.formatter = nil if $VERBOSE
24
+
25
+ ez.start_servers do
26
+ ez.server "simple-server", :tcp, nil, 0 do |svr|
27
+ Thread.new do
28
+ loop do
29
+ Thread.new(svr.accept) do |conn|
30
+ log.info "accepted connection from #{conn.inspect}"
31
+ conn.write "hello from #{log.progname}"
32
+ log.info "wrote greeting"
33
+ conn.close_write
34
+ log.info "trying to read from #{conn.inspect}"
35
+ log.info "received: #{conn.read}"
36
+ conn.close
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ ez.remote "simple-server", host: addr_there, eval: %{
44
+ conn = conns[0]
45
+ # this code is executed on the remote host, connected by conn, not drb
46
+ log.progname = "eval remote on \#{host}"
47
+ log.info "trying to read from \#{conn.inspect}"
48
+ log.info "received: \#{conn.read}"
49
+ conn.write "hello from \#{log.progname}"
50
+ conn.close
51
+ }
52
+ # Note use of \#{} to interpolate variables that are only available
53
+ # in the binding where the code is eval-ed. Alternately, use
54
+ # eval: %Q{...}
55
+ # but then interpolation from this script is not posssible.
56
+ end
@@ -4,7 +4,8 @@ servers_file = ARGV.shift
4
4
  unless servers_file
5
5
  abort <<-END
6
6
  Usage: #$0 servers_file
7
- For the client, copy the generated servers_file to the client host.
7
+ For the client, copy the generated servers_file to the client host, and
8
+ run with the same command.
8
9
  END
9
10
  end
10
11
 
@@ -0,0 +1,19 @@
1
+ class RemoteRunScript
2
+ attr_reader :conns, :host, :log, :args
3
+
4
+ def initialize conns, host, log, *args
5
+ @conns = conns
6
+ @host = host
7
+ @log = log
8
+ @args = args
9
+ end
10
+
11
+ def run
12
+ conn = conns[0]
13
+ log.progname = "run remote on #{host}"
14
+ log.info "trying to read from #{conn.inspect}"
15
+ log.info "received: #{conn.read}"
16
+ conn.write "hello from #{log.progname}"
17
+ conn.close
18
+ end
19
+ end
@@ -0,0 +1,53 @@
1
+ require 'easy-serve/remote'
2
+
3
+ addr_there = ARGV.shift
4
+
5
+ unless addr_there
6
+ abort <<-END
7
+
8
+ Usage: #$0 addr_there
9
+
10
+ The 'addr_there' is the remote address on which client code will run.
11
+ It must be a destination accepted by ssh, optionally including a user name:
12
+
13
+ [user@]hostname
14
+
15
+ The 'hostname' may by any valid hostname or ssh alias.
16
+
17
+ Note: you must set up the remote by doing
18
+
19
+ scp examples/remote-run-script.rb addr_there:/tmp/
20
+
21
+ END
22
+ end
23
+
24
+ EasyServe.start do |ez|
25
+ log = ez.log
26
+ log.level = Logger::INFO
27
+ log.formatter = nil if $VERBOSE
28
+
29
+ ez.start_servers do
30
+ ez.server "simple-server", :tcp, nil, 0 do |svr|
31
+ Thread.new do
32
+ loop do
33
+ Thread.new(svr.accept) do |conn|
34
+ log.info "accepted connection from #{conn.inspect}"
35
+ conn.write "hello from #{log.progname}"
36
+ log.info "wrote greeting"
37
+ conn.close_write
38
+ log.info "trying to read from #{conn.inspect}"
39
+ log.info "received: #{conn.read}"
40
+ conn.close
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ ez.remote "simple-server", host: addr_there,
48
+ dir: "/tmp",
49
+ file: "remote-run-script.rb",
50
+ # 'file' passed to load, so can be rel to dir or ruby's $LOAD_PATH
51
+ class_name: "RemoteRunScript",
52
+ args: []
53
+ end
data/lib/easy-serve.rb CHANGED
@@ -4,7 +4,7 @@ require 'yaml'
4
4
  require 'fileutils'
5
5
 
6
6
  class EasyServe
7
- VERSION = "0.3"
7
+ VERSION = "0.4"
8
8
 
9
9
  class Server
10
10
  attr_reader :name, :pid, :addr
@@ -58,17 +58,19 @@ class EasyServe
58
58
  @clients = [] # pid
59
59
  @passive_clients = [] # pid
60
60
  @owner = false
61
- @servers = nil # name => Server
61
+ @servers = opts[:servers] # name => Server
62
62
 
63
- if servers_file
64
- @servers =
65
- begin
66
- load_server_table
67
- rescue Errno::ENOENT
68
- init_server_table
69
- end
70
- else
71
- init_server_table
63
+ unless servers
64
+ if servers_file
65
+ @servers =
66
+ begin
67
+ load_server_table
68
+ rescue Errno::ENOENT
69
+ init_server_table
70
+ end
71
+ else
72
+ init_server_table
73
+ end
72
74
  end
73
75
  end
74
76
 
@@ -167,11 +169,27 @@ class EasyServe
167
169
  name =~ /-\d+\z/ ? name.succ : name + "-0"
168
170
  end
169
171
 
172
+ def host_name
173
+ @host_name ||= begin
174
+ hn = Socket.gethostname
175
+ begin
176
+ official_hostname = Socket.gethostbyname(hn)[0]
177
+ if /\./ =~ official_hostname
178
+ official_hostname
179
+ else
180
+ official_hostname + ".local"
181
+ end
182
+ rescue
183
+ 'localhost'
184
+ end
185
+ end
186
+ end
187
+
170
188
  def server name, proto = :unix, host = nil, port = nil
171
189
  server_class, *server_addr =
172
190
  case proto
173
191
  when /unix/i; [UNIXServer, choose_socket_filename(name, base: host)]
174
- when /tcp/i; [TCPServer, host || '127.0.0.1', port || 0]
192
+ when /tcp/i; [TCPServer, host || host_name, port || 0]
175
193
  else raise ArgumentError, "Unknown socket protocol: #{proto.inspect}"
176
194
  end
177
195
 
@@ -264,6 +282,9 @@ class EasyServe
264
282
  else TCPSocket
265
283
  end
266
284
  socket_class.new(*addr)
285
+ rescue => ex
286
+ ex.message << " addr=#{addr.inspect}"
287
+ raise
267
288
  end
268
289
 
269
290
  # ^C in the irb session (parent process) should not kill the
@@ -0,0 +1,94 @@
1
+ require 'drb'
2
+
3
+ class EasyServe
4
+ # useful for testing only -- use _eval or _run for production
5
+ def remote_drb *server_names, host: nil
6
+ ## passive option?
7
+ ## remote logfile option?
8
+
9
+ DRb.start_service("druby://#{host_name}:0", nil)
10
+
11
+ hostname = host.sub(/.*@/,"")
12
+ host_uri = "druby://#{hostname}:0"
13
+
14
+ log.progname = "remote_drb #{host}"
15
+
16
+ IO.popen ["ssh", host, "ruby"], "w+" do |ssh|
17
+ ssh.puts %Q{
18
+ $stdout.sync = true
19
+ begin
20
+ require 'drb'
21
+ require 'yaml'
22
+ require 'easy-serve'
23
+
24
+ server_names = #{server_names.inspect}
25
+ servers = YAML.load(#{YAML.dump(servers).inspect})
26
+ log_level = #{log.level}
27
+ host_uri = #{host_uri.inspect}
28
+
29
+ EasyServe.start servers: servers do |ez|
30
+ log = ez.log
31
+ log.level = log_level
32
+ log.formatter = nil if $VERBOSE
33
+
34
+ ez.local *server_names do |*conns|
35
+ begin
36
+ DRb.start_service(host_uri, {conns: conns})
37
+ puts DRb.uri
38
+
39
+ Thread.new do
40
+ loop do
41
+ sleep 1
42
+ begin
43
+ puts "."
44
+ rescue
45
+ exit
46
+ end
47
+ end
48
+ end
49
+
50
+ DRb.thread.join
51
+
52
+ rescue => ex
53
+ puts "ez error", ex, ex.backtrace
54
+ end
55
+ end
56
+ end
57
+ rescue => ex
58
+ puts "ez error", ex, ex.backtrace
59
+ end
60
+ }
61
+
62
+ ssh.close_write
63
+ result = ssh.gets
64
+
65
+ if !result
66
+ raise RemoteError, "problem with ssh connection to remote"
67
+ else
68
+ error = result[/ez error/]
69
+ if error
70
+ raise RemoteError, "error raised in remote: #{ssh.read}"
71
+ else
72
+ uri = result[/druby:\/\/\S+/]
73
+ if uri
74
+ Thread.new do
75
+ loop do
76
+ ssh.gets # consume the "."
77
+ end
78
+ end
79
+
80
+ log.debug "remote is at #{uri}"
81
+ ro = DRbObject.new_with_uri(uri)
82
+ conns = ro[:conns]
83
+ conns_ary = []
84
+ conns.each {|c| conns_ary << c} # needed because it's a DRbObject
85
+ yield(*conns_ary) if block_given?
86
+ else
87
+ raise RemoteError,
88
+ "no druby uri in string from remote: #{result.inspect}"
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,63 @@
1
+ class EasyServe
2
+ # useful simple cases in testing and in production, but long eval strings
3
+ # can be hard to debug -- use _run instead
4
+ def remote_eval *server_names, host: nil, **opts
5
+ ## passive option?
6
+ ## remote logfile option?
7
+
8
+ log.progname = "remote_eval #{host}"
9
+
10
+ IO.popen ["ssh", host, "ruby"], "w+" do |ssh|
11
+ ssh.puts %Q{
12
+ $stdout.sync = true
13
+ begin
14
+ require 'yaml'
15
+ require 'easy-serve'
16
+
17
+ class EasyServe
18
+ def binding_for_remote_eval conns, host, log
19
+ binding
20
+ end
21
+ end
22
+
23
+ server_names = #{server_names.inspect}
24
+ servers = YAML.load(#{YAML.dump(servers).inspect})
25
+ log_level = #{log.level}
26
+ eval_string = #{opts[:eval].inspect}
27
+ host = #{host.inspect}
28
+
29
+ EasyServe.start servers: servers do |ez|
30
+ log = ez.log
31
+ log.level = log_level
32
+ log.formatter = nil if $VERBOSE
33
+
34
+ ez.local *server_names do |*conns|
35
+ begin
36
+ eval eval_string, ez.binding_for_remote_eval(conns, host, log)
37
+ rescue => ex
38
+ puts "ez error", ex, ex.backtrace
39
+ end
40
+ end
41
+ end
42
+ rescue => ex
43
+ puts "ez error", ex, ex.backtrace
44
+ end
45
+ }
46
+
47
+ ssh.close_write
48
+ result = ssh.gets
49
+
50
+ if result
51
+ error = result[/ez error/]
52
+ if error
53
+ raise RemoteError, "error raised in remote: #{ssh.read}"
54
+ else
55
+ puts result
56
+ while s = ssh.gets
57
+ puts s
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,61 @@
1
+ class EasyServe
2
+ # useful in production, though it requires remote lib files to be set up
3
+ def remote_run *server_names, host: nil, **opts
4
+ ## passive option?
5
+ ## remote logfile option?
6
+
7
+ log.progname = "remote_run #{host}"
8
+
9
+ IO.popen ["ssh", host, "ruby"], "w+" do |ssh|
10
+ ssh.puts %Q{
11
+ $stdout.sync = true
12
+ begin
13
+ require 'yaml'
14
+ require 'easy-serve'
15
+
16
+ server_names = #{server_names.inspect}
17
+ servers = YAML.load(#{YAML.dump(servers).inspect})
18
+ log_level = #{log.level}
19
+ host = #{host.inspect}
20
+ args = YAML.load(#{YAML.dump(opts[:args]).inspect})
21
+
22
+ #{opts[:dir] && "Dir.chdir #{opts[:dir].inspect}"}
23
+ load #{opts[:file].inspect}
24
+
25
+ EasyServe.start servers: servers do |ez|
26
+ log = ez.log
27
+ log.level = log_level
28
+ log.formatter = nil if $VERBOSE
29
+
30
+ ez.local *server_names do |*conns|
31
+ begin
32
+ cl = Object.const_get(#{opts[:class_name].inspect})
33
+ ro = cl.new(conns, host, log, *args)
34
+ ro.run
35
+ rescue => ex
36
+ puts "ez error", ex, ex.backtrace
37
+ end
38
+ end
39
+ end
40
+ rescue => ex
41
+ puts "ez error", ex, ex.backtrace
42
+ end
43
+ }
44
+
45
+ ssh.close_write
46
+ result = ssh.gets
47
+
48
+ if result
49
+ error = result[/ez error/]
50
+ if error
51
+ raise RemoteError, "error raised in remote: #{ssh.read}"
52
+ else
53
+ puts result
54
+ while s = ssh.gets
55
+ puts s
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,25 @@
1
+ require 'easy-serve'
2
+
3
+ class EasyServe
4
+ class RemoteError < RuntimeError; end
5
+
6
+ def remote *server_names, host: nil, **opts
7
+ raise ArgumentError, "no host specified" unless host
8
+
9
+ if opts[:eval]
10
+ require 'easy-serve/remote-eval'
11
+ remote_eval *server_names, host: host, **opts
12
+
13
+ elsif opts[:file]
14
+ require 'easy-serve/remote-run'
15
+ remote_run *server_names, host: host, **opts
16
+
17
+ elsif block_given?
18
+ require 'easy-serve/remote-drb'
19
+ remote_drb *server_names, host: host, **opts, &Proc.new
20
+
21
+ else
22
+ raise ArgumentError, "cannot select remote mode based on arguments"
23
+ end
24
+ end
25
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy-serve
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.3'
4
+ version: '0.4'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel VanderWerf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-31 00:00:00.000000000 Z
11
+ date: 2013-08-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Framework for starting tcp/unix servers and connected clients under one
14
14
  parent process.
@@ -22,9 +22,17 @@ files:
22
22
  - README.md
23
23
  - COPYING
24
24
  - lib/easy-serve.rb
25
+ - lib/easy-serve/remote-run.rb
26
+ - lib/easy-serve/remote-drb.rb
27
+ - lib/easy-serve/remote.rb
28
+ - lib/easy-serve/remote-eval.rb
25
29
  - examples/simple.rb
30
+ - examples/remote-manual.rb
26
31
  - examples/multi.rb
27
- - examples/remote.rb
32
+ - examples/remote-run.rb
33
+ - examples/remote-drb.rb
34
+ - examples/remote-run-script.rb
35
+ - examples/remote-eval.rb
28
36
  - examples/passive.rb
29
37
  homepage: https://github.com/vjoel/easy-serve
30
38
  licenses: