easy-serve 0.3 → 0.4

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