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.
- checksums.yaml +7 -0
- data/.rubocop.yml +10 -0
- data/LICENSE +24 -0
- data/dizby.gemspec +27 -0
- data/lib/dizby.rb +12 -0
- data/lib/dizby/access/control_list.rb +78 -0
- data/lib/dizby/access/entry.rb +61 -0
- data/lib/dizby/access/insecure.rb +30 -0
- data/lib/dizby/access/list.rb +10 -0
- data/lib/dizby/converter/simple.rb +12 -0
- data/lib/dizby/converter/timed.rb +23 -0
- data/lib/dizby/distributed/array.rb +30 -0
- data/lib/dizby/distributed/object.rb +44 -0
- data/lib/dizby/distributed/proxy.rb +41 -0
- data/lib/dizby/distributed/semi_proxy.rb +26 -0
- data/lib/dizby/distributed/undumpable.rb +8 -0
- data/lib/dizby/distributed/unknown.rb +57 -0
- data/lib/dizby/error.rb +29 -0
- data/lib/dizby/protocol/basic.rb +31 -0
- data/lib/dizby/protocol/manager.rb +62 -0
- data/lib/dizby/protocol/refined.rb +23 -0
- data/lib/dizby/protocols/dead.rb +24 -0
- data/lib/dizby/protocols/secure.rb +87 -0
- data/lib/dizby/protocols/tcp.rb +98 -0
- data/lib/dizby/protocols/unix.rb +95 -0
- data/lib/dizby/server/abstract.rb +42 -0
- data/lib/dizby/server/basic.rb +101 -0
- data/lib/dizby/server/registration.rb +23 -0
- data/lib/dizby/service.rb +64 -0
- data/lib/dizby/stream/client.rb +26 -0
- data/lib/dizby/stream/connection.rb +63 -0
- data/lib/dizby/stream/messenger.rb +28 -0
- data/lib/dizby/stream/query_ref.rb +13 -0
- data/lib/dizby/stream/readable.rb +65 -0
- data/lib/dizby/stream/writable.rb +37 -0
- data/lib/dizby/tunnel/abstract.rb +52 -0
- data/lib/dizby/tunnel/basic.rb +21 -0
- data/lib/dizby/tunnel/basic_spawn.rb +50 -0
- data/lib/dizby/tunnel/bidirectional_strategy.rb +29 -0
- data/lib/dizby/tunnel/factory.rb +29 -0
- data/lib/dizby/tunnel/local_strategy.rb +24 -0
- data/lib/dizby/tunnel/spawn_command.rb +49 -0
- data/lib/dizby/tunnel/spawned.rb +43 -0
- data/lib/dizby/tunnel/tunnelable_local.rb +8 -0
- data/lib/dizby/tunnel/tunnelable_remote.rb +21 -0
- data/lib/dizby/utility/classic_access.rb +25 -0
- data/lib/dizby/utility/configurable.rb +25 -0
- data/lib/dizby/utility/delegator.rb +28 -0
- data/lib/dizby/utility/io_barrier.rb +18 -0
- data/lib/dizby/utility/log.rb +23 -0
- data/lib/dizby/utility/monitor.rb +9 -0
- data/lib/dizby/utility/polymorphic_delegated.rb +58 -0
- data/lib/dizby/utility/self_pipe.rb +12 -0
- data/lib/dizby/utility/semi_built.rb +17 -0
- data/lib/dizby/utility/string.rb +8 -0
- data/lib/dizby/utility/timed_collection.rb +39 -0
- data/lib/dizby/utility/timed_state.rb +41 -0
- data/lib/dizby/version.rb +4 -0
- data/lib/dizby/worker/connection.rb +44 -0
- data/lib/dizby/worker/invoke_method.rb +55 -0
- data/lib/dizby/worker/server.rb +39 -0
- 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,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,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
|