dizby 1.3.0

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.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +10 -0
  3. data/LICENSE +24 -0
  4. data/dizby.gemspec +27 -0
  5. data/lib/dizby.rb +12 -0
  6. data/lib/dizby/access/control_list.rb +78 -0
  7. data/lib/dizby/access/entry.rb +61 -0
  8. data/lib/dizby/access/insecure.rb +30 -0
  9. data/lib/dizby/access/list.rb +10 -0
  10. data/lib/dizby/converter/simple.rb +12 -0
  11. data/lib/dizby/converter/timed.rb +23 -0
  12. data/lib/dizby/distributed/array.rb +30 -0
  13. data/lib/dizby/distributed/object.rb +44 -0
  14. data/lib/dizby/distributed/proxy.rb +41 -0
  15. data/lib/dizby/distributed/semi_proxy.rb +26 -0
  16. data/lib/dizby/distributed/undumpable.rb +8 -0
  17. data/lib/dizby/distributed/unknown.rb +57 -0
  18. data/lib/dizby/error.rb +29 -0
  19. data/lib/dizby/protocol/basic.rb +31 -0
  20. data/lib/dizby/protocol/manager.rb +62 -0
  21. data/lib/dizby/protocol/refined.rb +23 -0
  22. data/lib/dizby/protocols/dead.rb +24 -0
  23. data/lib/dizby/protocols/secure.rb +87 -0
  24. data/lib/dizby/protocols/tcp.rb +98 -0
  25. data/lib/dizby/protocols/unix.rb +95 -0
  26. data/lib/dizby/server/abstract.rb +42 -0
  27. data/lib/dizby/server/basic.rb +101 -0
  28. data/lib/dizby/server/registration.rb +23 -0
  29. data/lib/dizby/service.rb +64 -0
  30. data/lib/dizby/stream/client.rb +26 -0
  31. data/lib/dizby/stream/connection.rb +63 -0
  32. data/lib/dizby/stream/messenger.rb +28 -0
  33. data/lib/dizby/stream/query_ref.rb +13 -0
  34. data/lib/dizby/stream/readable.rb +65 -0
  35. data/lib/dizby/stream/writable.rb +37 -0
  36. data/lib/dizby/tunnel/abstract.rb +52 -0
  37. data/lib/dizby/tunnel/basic.rb +21 -0
  38. data/lib/dizby/tunnel/basic_spawn.rb +50 -0
  39. data/lib/dizby/tunnel/bidirectional_strategy.rb +29 -0
  40. data/lib/dizby/tunnel/factory.rb +29 -0
  41. data/lib/dizby/tunnel/local_strategy.rb +24 -0
  42. data/lib/dizby/tunnel/spawn_command.rb +49 -0
  43. data/lib/dizby/tunnel/spawned.rb +43 -0
  44. data/lib/dizby/tunnel/tunnelable_local.rb +8 -0
  45. data/lib/dizby/tunnel/tunnelable_remote.rb +21 -0
  46. data/lib/dizby/utility/classic_access.rb +25 -0
  47. data/lib/dizby/utility/configurable.rb +25 -0
  48. data/lib/dizby/utility/delegator.rb +28 -0
  49. data/lib/dizby/utility/io_barrier.rb +18 -0
  50. data/lib/dizby/utility/log.rb +23 -0
  51. data/lib/dizby/utility/monitor.rb +9 -0
  52. data/lib/dizby/utility/polymorphic_delegated.rb +58 -0
  53. data/lib/dizby/utility/self_pipe.rb +12 -0
  54. data/lib/dizby/utility/semi_built.rb +17 -0
  55. data/lib/dizby/utility/string.rb +8 -0
  56. data/lib/dizby/utility/timed_collection.rb +39 -0
  57. data/lib/dizby/utility/timed_state.rb +41 -0
  58. data/lib/dizby/version.rb +4 -0
  59. data/lib/dizby/worker/connection.rb +44 -0
  60. data/lib/dizby/worker/invoke_method.rb +55 -0
  61. data/lib/dizby/worker/server.rb +39 -0
  62. metadata +146 -0
@@ -0,0 +1,52 @@
1
+
2
+ require 'net/ssh'
3
+
4
+ module Dizby
5
+ class AbstractTunnel
6
+ def initialize(server, strategy, user, host)
7
+ @server = server
8
+ @config = [user, host, @server.config[:ssh_config]]
9
+ @strategy = strategy
10
+
11
+ reader, writer = IO.pipe
12
+
13
+ @thread = Thread.start do
14
+ open_ssh(writer)
15
+ writer.close
16
+ end
17
+
18
+ @thread.abort_on_exception = true
19
+
20
+ read_ports(reader)
21
+ reader.close
22
+ end
23
+
24
+ # wait(ssh) is not defined in this class
25
+ def open_ssh(output)
26
+ ssh = nil
27
+ begin
28
+ ssh = Net::SSH.start(*@config)
29
+
30
+ get_and_write_ports(ssh, output)
31
+
32
+ wait(ssh)
33
+ ensure
34
+ ssh.close if ssh
35
+ end
36
+ end
37
+
38
+ def read_ports(input)
39
+ @local_port, @remote_port = @strategy.read(input)
40
+ end
41
+
42
+ def get_and_write_ports(ssh, output)
43
+ @strategy.write(ssh, output)
44
+ end
45
+
46
+ def close
47
+ @thread.join
48
+ end
49
+
50
+ attr_reader :local_port, :remote_port
51
+ end
52
+ end
@@ -0,0 +1,21 @@
1
+
2
+ require 'dizby/tunnel/abstract'
3
+
4
+ module Dizby
5
+ class BasicTunnel < AbstractTunnel
6
+ def initialize(server, strategy, user, host)
7
+ @working = true
8
+
9
+ super(server, strategy, user, host)
10
+ end
11
+
12
+ def wait(ssh)
13
+ ssh.loop { @working }
14
+ end
15
+
16
+ def close # TODO: test this
17
+ @working = false
18
+ super
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,50 @@
1
+
2
+ require 'dizby/tunnel/abstract'
3
+ require 'dizby/error'
4
+
5
+ module Dizby
6
+ class BasicSpawnTunnel < AbstractTunnel
7
+ def initialize(server, strategy, command, user, host)
8
+ @command = command
9
+
10
+ super(server, strategy, user, host)
11
+ end
12
+
13
+ def get_and_write_ports(ssh, output)
14
+ @command.set_dynamic_mode unless @tunnel.server_port
15
+
16
+ @channel = ssh.open_channel do |ch|
17
+ ch.exec @command.to_cmd do |_, success|
18
+ fail SpawnError, 'could not spawn host' unless success
19
+
20
+ # it is already triggered if the port is set
21
+ get_remote_server_port(ch) if @command.dynamic?
22
+ end
23
+ end
24
+
25
+ ssh.loop { !@channel[:triggered] } if @command.dynamic?
26
+ @channel.eof!
27
+
28
+ super
29
+ end
30
+
31
+ def get_remote_server_port(ch)
32
+ ch[:data] = ''
33
+ ch[:triggered] = false
34
+
35
+ ch.on_data { |_, data| ch[:data] << data }
36
+ ch.on_extended_data { |_, _, data| @server.log(data.inspect) }
37
+
38
+ ch.on_process do |_|
39
+ if !ch[:triggered] && ch[:data] =~ /Running on port (\d+)\./
40
+ @strategy.instance_variable_set(:@server_port, $~[1])
41
+ ch[:triggered] = true
42
+ end
43
+ end
44
+ end
45
+
46
+ def wait(ssh)
47
+ ssh.loop { @channel.active? }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,29 @@
1
+
2
+ require 'dizby/tunnel/tunnelable_local'
3
+ require 'dizby/tunnel/tunnelable_remote'
4
+
5
+ module Dizby
6
+ class BidirectionalTunnelStrategy
7
+ include TunnelableLocal
8
+ include TunnelableRemote
9
+
10
+ def initialize(server_port, client_port)
11
+ @server_port = server_port
12
+ @client_port = client_port
13
+ end
14
+
15
+ def write(ssh, stream)
16
+ local_tunnel = create_local_tunnel(ssh, @server_port)
17
+ remote_tunnel = create_remote_tunnel(ssh, @client_port)
18
+
19
+ stream.puts local_tunnel, remote_tunnel
20
+ end
21
+
22
+ def read(stream)
23
+ local_tunnel = stream.gets.chomp.to_i
24
+ remote_tunnel = stream.gets.chomp.to_i
25
+
26
+ [local_tunnel, remote_tunnel]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+
2
+ require 'dizby/tunnel/local_strategy'
3
+ require 'dizby/tunnel/bidirectional_strategy'
4
+ require 'dizby/utility/semi_built'
5
+
6
+ module Dizby
7
+ class TunnelFactory
8
+ def initialize(server, port)
9
+ @server = server
10
+ @port = port
11
+ end
12
+
13
+ def create(type)
14
+ SemibuiltObject.new(type, @server, strategy)
15
+ end
16
+
17
+ def bidirectional?
18
+ @server.respond_to?(:port)
19
+ end
20
+
21
+ def strategy
22
+ if bidirectional?
23
+ BidirectionalTunnelStrategy.new(@port, @server.port)
24
+ else
25
+ LocalTunnelStrategy.new(@port)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+
2
+ require 'dizby/tunnel/tunnelable_local'
3
+
4
+ module Dizby
5
+ class LocalTunnelStrategy
6
+ include TunnelableLocal
7
+
8
+ def initialize(server_port)
9
+ @server_port = server_port
10
+ end
11
+
12
+ def write(ssh, stream)
13
+ local_tunnel = create_local_tunnel(ssh, @server_port)
14
+
15
+ stream.puts local_tunnel
16
+ end
17
+
18
+ def read(stream)
19
+ local_tunnel = stream.gets.chomp.to_i
20
+
21
+ [local_tunnel, nil]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,49 @@
1
+
2
+ require 'shellwords'
3
+
4
+ module Dizby
5
+ class SpawnCommand
6
+ TEMPLATE = "require'dizby/tunnel/spawned';Dizby::Spawned.%s('%s',%s){%s}"
7
+
8
+ def initialize(data, config = {})
9
+ @data = data
10
+ @ruby_cmd = 'ruby'
11
+ @uri = 'drb://'
12
+ @config = config
13
+ @mode = :static
14
+ end
15
+
16
+ def set_dynamic_mode
17
+ @mode = :dynamic
18
+ end
19
+
20
+ def dynamic?
21
+ @mode == :dynamic
22
+ end
23
+
24
+ attr_accessor :ruby_cmd, :config, :uri
25
+
26
+ def to_cmd
27
+ # TODO: needs a lot of work...
28
+ args = [@mode, @uri.shellescape, @config.inspect, @data.shellescape]
29
+ [@ruby_cmd, '-e', %("#{TEMPLATE % args}")].join ' '
30
+ end
31
+ alias_method :to_s, :to_cmd
32
+
33
+ class << self
34
+ def text(script)
35
+ new(script)
36
+ end
37
+
38
+ def local_file(file)
39
+ new(File.read(file))
40
+ end
41
+
42
+ # WARNING: Dangerous operation. This loads an object from a file on the
43
+ # remote machine. That file may be insecure or modified without notice.
44
+ def remote_file(file, obj_name)
45
+ new("load '#{file}'; #{obj_name}")
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,43 @@
1
+
2
+ # require the whole package, minimizes command length
3
+ require 'dizby'
4
+ require 'dizby/utility/io_barrier'
5
+
6
+ module Dizby
7
+ class Spawned
8
+ def self.static(uri, config, &block)
9
+ handle_spawned(uri, config, block)
10
+ end
11
+
12
+ def self.dynamic(uri, config, &block)
13
+ handle_spawned(uri, config, block) do |service|
14
+ $stdout.puts "Running on port #{service.server.port}."
15
+ end
16
+ end
17
+
18
+ def self.handle_spawned(uri, config, origin)
19
+ service = nil
20
+
21
+ obj = obtain_object(&origin)
22
+
23
+ obj.define_singleton_method :__dizby_exit__ do
24
+ service.close if service
25
+ end
26
+
27
+ service = Service.new(uri, obj, Marshal.load(config))
28
+ yield service if block_given?
29
+ ensure
30
+ service.wait if service
31
+ end
32
+
33
+ def self.obtain_object(&origin)
34
+ barriers = [$stdout, $stdin, $stderr].map { |io| IOBarrier.new(io) }
35
+
36
+ barriers.each(&:block)
37
+
38
+ origin.call
39
+ ensure
40
+ barriers.each(&:allow)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,8 @@
1
+
2
+ module Dizby
3
+ module TunnelableLocal
4
+ def create_local_tunnel(ssh, server_port)
5
+ ssh.forward.local 0, 'localhost', server_port
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+
2
+ module Dizby
3
+ module TunnelableRemote
4
+ def create_remote_tunnel(ssh, client_port)
5
+ remote_tunnel_port = nil
6
+ ssh.forward.remote client_port, 'localhost',
7
+ 0, 'localhost' do |remote_port|
8
+ remote_tunnel_port = remote_port
9
+ :no_exception
10
+ end
11
+
12
+ ssh.loop { remote_tunnel_port.nil? }
13
+
14
+ if remote_tunnel_port == :error
15
+ fail Net::SSH::Exception, 'remote forwarding request failed'
16
+ end
17
+
18
+ remote_tunnel_port
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+
2
+ module Dizby
3
+ module ClassicAttributeAccess
4
+ def attr_reader(*args)
5
+ args.each do |method|
6
+ define_method(method) do
7
+ instance_variable_get(:"@#{method}")
8
+ end
9
+ end
10
+ end
11
+
12
+ def attr_writer(*args)
13
+ args.each do |method|
14
+ define_method("#{method}=") do |value|
15
+ instance_variable_set(:"@#{method}", value)
16
+ end
17
+ end
18
+ end
19
+
20
+ def attr_accessor(*args)
21
+ attr_reader(*args)
22
+ attr_writer(*args)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+
2
+ module Dizby
3
+ module Configurable
4
+ def config_reader(*args)
5
+ args.each do |method|
6
+ define_method(method) do
7
+ instance_variable_get(:@config)[method]
8
+ end
9
+ end
10
+ end
11
+
12
+ def config_writer(*args)
13
+ args.each do |method|
14
+ define_method("#{method}=") do |value|
15
+ instance_variable_get(:@config)[method] = value
16
+ end
17
+ end
18
+ end
19
+
20
+ def config_accessor(*args)
21
+ config_reader(*args)
22
+ config_writer(*args)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+
2
+ module Dizby
3
+ class Delegator
4
+ def initialize(obj)
5
+ @__delegated_object__ = obj
6
+ end
7
+
8
+ def instance_variable_get(sym)
9
+ @__delegated_object__.instance_variable_get(sym)
10
+ end
11
+
12
+ def instance_variable_set(sym, value)
13
+ @__delegated_object__.instance_variable_set(sym, value)
14
+ end
15
+
16
+ def __undelegated_get__(sym)
17
+ __instance_variable_get__(sym)
18
+ end
19
+
20
+ def __undelegated_set__(sym, value)
21
+ __instance_variable_set__(sym, value)
22
+ end
23
+
24
+ def method_missing(name, *args, &block)
25
+ @__delegated_object__.__delegate__(name, self, *args, &block)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+
2
+ module Dizby
3
+ class IOBarrier
4
+ def initialize(var)
5
+ @var = var
6
+ @orig = var.dup
7
+ end
8
+
9
+ def block
10
+ @var.reopen(File::NULL)
11
+ end
12
+
13
+ def allow
14
+ @var.reopen(@orig)
15
+ @var.sync = true
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+
2
+ require 'logger'
3
+
4
+ module Dizby
5
+ def self.create_logger(config, &transformer)
6
+ log = Logger.new(config[:output])
7
+
8
+ default_formatter = Logger::Formatter.new
9
+ log.formatter = proc do |severity, datetime, progname, msg|
10
+ msg = transformer.call(msg) if transformer
11
+ default_formatter.call(severity, datetime, progname, msg)
12
+ end
13
+
14
+ log.level = config[:level]
15
+
16
+ log.define_singleton_method(:backtrace) do |exception|
17
+ error(exception.inspect)
18
+ exception.backtrace.each { |trace| error(trace) }
19
+ end
20
+
21
+ log
22
+ end
23
+ end