xlogin 0.9.0 → 0.9.2
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 +4 -4
- data/lib/xlogin.rb +3 -3
- data/lib/xlogin/delegator.rb +1 -1
- data/lib/xlogin/factory.rb +25 -12
- data/lib/xlogin/session.rb +43 -57
- data/lib/xlogin/session_pool.rb +20 -39
- data/lib/xlogin/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7920c6bfed2e33fd3aa7e60128ae9b01b2464dec
|
4
|
+
data.tar.gz: 6304076fbb457c60020f8fd8875ea147bd162d85
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9a8f8cbf8ae3eed54beeca00efbbdaf080f98fea77f7c1064d1b904c6d9f2b58fa34e287b406d20327690cb2d01ba4d493f7b1d9da531cb3b7cd9628a3b8535
|
7
|
+
data.tar.gz: 03ee0f923e53ddc0f10fc7b37ddd7b20f279da1fe2bbb3db202aeffef6ba3c6b49d93f27c51aab095a2b24f0c7367ecc4d06f16e6df4f74134da7b81011ab9d3
|
data/lib/xlogin.rb
CHANGED
@@ -27,11 +27,11 @@ module Xlogin
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def list(*patterns)
|
30
|
-
factory.
|
30
|
+
factory.list_inventory(*patterns)
|
31
31
|
end
|
32
32
|
|
33
33
|
def get_pool(args, **opts, &block)
|
34
|
-
pool =
|
34
|
+
pool = factory.build_pool(args, **opts)
|
35
35
|
|
36
36
|
return pool unless block
|
37
37
|
block.call(pool)
|
@@ -57,7 +57,7 @@ module Xlogin
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def register(**args)
|
60
|
-
factory.
|
60
|
+
factory.set_inventory(**args)
|
61
61
|
end
|
62
62
|
|
63
63
|
def source(*source_files)
|
data/lib/xlogin/delegator.rb
CHANGED
@@ -9,7 +9,7 @@ module Xlogin
|
|
9
9
|
target_host = params.delete(:relay)
|
10
10
|
return super(uri, **params) unless target_host
|
11
11
|
|
12
|
-
target_info = Xlogin.factory.
|
12
|
+
target_info = Xlogin.factory.get_inventory(target_host)
|
13
13
|
target_temp = Xlogin.factory.get_template(target_info[:type])
|
14
14
|
target_uri = Addressable::URI.parse(target_info[:uri])
|
15
15
|
|
data/lib/xlogin/factory.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'addressable/uri'
|
1
2
|
require 'singleton'
|
2
3
|
require 'xlogin/template'
|
3
4
|
|
@@ -11,17 +12,16 @@ module Xlogin
|
|
11
12
|
@templates = Hash.new
|
12
13
|
end
|
13
14
|
|
14
|
-
def
|
15
|
-
name = opts[:name]
|
16
|
-
|
17
|
-
@inventory[name] = (get_info(name) || {}).merge(opts)
|
15
|
+
def set_inventory(**opts)
|
16
|
+
return unless name = opts[:name]
|
17
|
+
@inventory[name] = (get_inventory(name) || {}).merge(opts)
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def get_inventory(name)
|
21
21
|
@inventory[name]
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
24
|
+
def list_inventory(*patterns)
|
25
25
|
return @inventory.values if patterns.empty?
|
26
26
|
|
27
27
|
values = patterns.map do |pattern|
|
@@ -47,16 +47,29 @@ module Xlogin
|
|
47
47
|
@templates.keys
|
48
48
|
end
|
49
49
|
|
50
|
-
def build(type:,
|
50
|
+
def build(type:, **opts)
|
51
51
|
template = get_template(type)
|
52
|
-
|
52
|
+
if opts[:uri]
|
53
|
+
template.build(opts[:uri], **opts)
|
54
|
+
else
|
55
|
+
scheme = opts[:scheme]
|
56
|
+
address = opts.values_at(:host, :port).compact.join(':')
|
57
|
+
userinfo = opts[:userinfo]
|
58
|
+
userinfo ||= opts.values_at(:username, :password).compact.join(':')
|
59
|
+
|
60
|
+
template.build("#{scheme}://" + [userinfo, address].compact.join('@'), **opts)
|
61
|
+
end
|
53
62
|
end
|
54
63
|
|
55
|
-
def build_from_hostname(
|
56
|
-
hostinfo =
|
57
|
-
raise SessionError.new("Host not found: '#{
|
64
|
+
def build_from_hostname(args, **opts)
|
65
|
+
hostinfo = get_inventory(args)
|
66
|
+
raise SessionError.new("Host not found: '#{args}'") unless hostinfo
|
67
|
+
|
68
|
+
build(hostinfo.merge(name: args, **opts))
|
69
|
+
end
|
58
70
|
|
59
|
-
|
71
|
+
def build_pool(args, **opts)
|
72
|
+
Xlogin::SessionPool.new(args, **opts)
|
60
73
|
end
|
61
74
|
|
62
75
|
end
|
data/lib/xlogin/session.rb
CHANGED
@@ -23,7 +23,7 @@ module Xlogin
|
|
23
23
|
|
24
24
|
raise SessionError.new("Invalid URI - '#{uri}'") unless @host && @port
|
25
25
|
|
26
|
-
@name = opts
|
26
|
+
@name = opts[:name] || @host
|
27
27
|
@config = OpenStruct.new(opts)
|
28
28
|
@template = template
|
29
29
|
@username, @password = uri.userinfo.to_s.split(':')
|
@@ -31,10 +31,8 @@ module Xlogin
|
|
31
31
|
ssh_tunnel(@config.via) if @config.via
|
32
32
|
max_retry = @config.retry || 1
|
33
33
|
|
34
|
-
@mutex
|
35
|
-
@
|
36
|
-
@output_logs = [@config.log]
|
37
|
-
@output_loggers = build_loggers
|
34
|
+
@mutex = Mutex.new
|
35
|
+
@loggers = [@config.log].flatten.uniq.reduce({}) { |a, e| a.merge(e => build_logger(e)) }
|
38
36
|
|
39
37
|
begin
|
40
38
|
super(
|
@@ -48,7 +46,6 @@ module Xlogin
|
|
48
46
|
)
|
49
47
|
rescue => e
|
50
48
|
retry if (max_retry -= 1) > 0
|
51
|
-
@closed = true
|
52
49
|
raise e
|
53
50
|
end
|
54
51
|
end
|
@@ -61,71 +58,65 @@ module Xlogin
|
|
61
58
|
cmd('').lines.last.chomp
|
62
59
|
end
|
63
60
|
|
64
|
-
def
|
65
|
-
@
|
61
|
+
def duplicate
|
62
|
+
@template.build(@uri, **@config.to_h)
|
66
63
|
end
|
67
64
|
|
68
65
|
def puts(*args, &block)
|
69
|
-
args = instance_exec(*args, &@template.interrupt) if @template.interrupt
|
66
|
+
args = [instance_exec(*args, &@template.interrupt)].flatten if @template.interrupt
|
70
67
|
super(*args, &block)
|
71
68
|
end
|
72
69
|
|
73
70
|
def waitfor(*args, &block)
|
74
|
-
|
75
|
-
line = super(*args) do |recv|
|
76
|
-
block.call(recv) if block
|
77
|
-
output_log(recv)
|
78
|
-
end
|
79
|
-
|
80
|
-
_, process = @template.prompt.find { |r, p| r =~ line && p }
|
81
|
-
if process
|
82
|
-
instance_eval(&process)
|
83
|
-
line += waitfor(*args, &block)
|
84
|
-
end
|
85
|
-
rescue EOFError
|
86
|
-
@closed = true
|
87
|
-
ensure
|
88
|
-
return line
|
71
|
+
@mutex.synchronize { _waitfor(*args, &block) }
|
89
72
|
end
|
90
73
|
|
91
74
|
def close
|
92
75
|
@mutex.synchronize do
|
93
|
-
@
|
94
|
-
next
|
95
|
-
logger.close
|
76
|
+
@loggers.values.each do |logger|
|
77
|
+
next if logger.nil? || [$stdout, $stderr].include?(logger)
|
78
|
+
logger.close
|
96
79
|
end
|
97
80
|
@gateway.shutdown! if @gateway
|
98
81
|
|
99
82
|
super
|
100
|
-
@closed = true
|
101
83
|
end
|
102
84
|
end
|
103
85
|
|
104
|
-
def
|
105
|
-
@
|
106
|
-
end
|
107
|
-
|
108
|
-
def duplicate
|
109
|
-
@template.build(@uri, **config.to_h)
|
110
|
-
end
|
111
|
-
|
112
|
-
def enable_log(out = $stdout)
|
113
|
-
@output_loggers = build_loggers(@output_logs + [out])
|
86
|
+
def enable_log(log = $stdout)
|
87
|
+
@loggers.update(log => build_loggers(log))
|
114
88
|
if block_given?
|
115
89
|
yield
|
116
|
-
|
90
|
+
disable_log(log)
|
117
91
|
end
|
118
92
|
end
|
119
93
|
|
120
|
-
def disable_log(
|
121
|
-
@
|
94
|
+
def disable_log(log = $stdout)
|
95
|
+
@loggers.delete(log)
|
122
96
|
if block_given?
|
123
97
|
yield
|
124
|
-
|
98
|
+
enable_log(log)
|
125
99
|
end
|
126
100
|
end
|
127
101
|
|
128
102
|
private
|
103
|
+
def _waitfor(*args, &block)
|
104
|
+
args << Regexp.union(*@template.prompt.map(&:first)) if args.empty?
|
105
|
+
line = method(:waitfor).super_method.call(*args) do |recv|
|
106
|
+
block.call(recv) if block
|
107
|
+
output_log(recv)
|
108
|
+
end
|
109
|
+
|
110
|
+
_, process = @template.prompt.find { |r, p| r =~ line && p }
|
111
|
+
if process
|
112
|
+
instance_eval(&process)
|
113
|
+
line += _waitfor(*args, &block)
|
114
|
+
end
|
115
|
+
rescue EOFError
|
116
|
+
ensure
|
117
|
+
return line
|
118
|
+
end
|
119
|
+
|
129
120
|
def ssh_tunnel(gateway)
|
130
121
|
gateway_uri = Addressable::URI.parse(gateway)
|
131
122
|
case gateway_uri.scheme
|
@@ -144,24 +135,19 @@ module Xlogin
|
|
144
135
|
end
|
145
136
|
|
146
137
|
def output_log(text)
|
147
|
-
@
|
148
|
-
next unless logger
|
149
|
-
logger.syswrite(text)
|
150
|
-
end
|
138
|
+
@loggers.values.each { |logger| logger.syswrite(text) if logger }
|
151
139
|
end
|
152
140
|
|
153
|
-
def
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
logger.sync = true
|
161
|
-
end
|
162
|
-
when IO, StringIO
|
163
|
-
loggers[output_log] = output_log
|
141
|
+
def build_logger(log)
|
142
|
+
case log
|
143
|
+
when String
|
144
|
+
FileUtils.mkdir_p(File.dirname(log))
|
145
|
+
File.open(log, 'a+').tap do |logger|
|
146
|
+
logger.binmode
|
147
|
+
logger.sync = true
|
164
148
|
end
|
149
|
+
when IO, StringIO
|
150
|
+
log
|
165
151
|
end
|
166
152
|
end
|
167
153
|
end
|
data/lib/xlogin/session_pool.rb
CHANGED
@@ -5,76 +5,57 @@ module Xlogin
|
|
5
5
|
class SessionPool
|
6
6
|
|
7
7
|
DEFAULT_SIZE = 1
|
8
|
-
DEFAULT_IDLE = false
|
9
8
|
|
10
9
|
def initialize(args, **opts)
|
11
|
-
@args
|
12
|
-
@opts
|
10
|
+
@args = args
|
11
|
+
@opts = opts
|
12
|
+
@size = case @args
|
13
|
+
when String then @opts.delete(:size) || DEFAULT_SIZE
|
14
|
+
when Hash then @args.delete(:size) || DEFAULT_SIZE
|
15
|
+
end
|
13
16
|
|
14
17
|
@mutex = Mutex.new
|
15
18
|
@queue = Queue.new
|
16
19
|
|
17
20
|
@created = 0
|
18
|
-
@watchdog = Hash.new
|
19
|
-
end
|
20
|
-
|
21
|
-
def size
|
22
|
-
case @args
|
23
|
-
when String then @opts[:size] || DEFAULT_SIZE
|
24
|
-
when Hash then @args[:size] || DEFAULT_SIZE
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def idle
|
29
|
-
case @args
|
30
|
-
when String then @opts[:idle] || DEFAULT_IDLE
|
31
|
-
when Hash then @args[:idle] || DEFAULT_IDLE
|
32
|
-
end
|
33
21
|
end
|
34
22
|
|
35
23
|
def with
|
36
24
|
session = deq
|
25
|
+
|
37
26
|
begin
|
38
|
-
|
39
|
-
|
40
|
-
|
27
|
+
session.prompt
|
28
|
+
rescue Errno::ECONNABORTED, Errno::ECONNREFUSED, Errno::ECONNRESET
|
29
|
+
session.close rescue nil
|
30
|
+
@created -= 1
|
31
|
+
session = try_create
|
41
32
|
end
|
33
|
+
|
34
|
+
Thread.handle_interrupt(Exception => :immediate) { yield session }
|
35
|
+
ensure
|
36
|
+
enq session
|
42
37
|
end
|
43
38
|
|
44
39
|
private
|
45
40
|
def deq
|
46
41
|
session = try_create
|
47
|
-
unless session
|
48
|
-
session, updated = @queue.deq
|
49
|
-
session = session.duplicate if idle && updated + idle.to_f < Time.now
|
50
|
-
end
|
51
|
-
|
42
|
+
session = @queue.deq unless session
|
52
43
|
session
|
53
44
|
end
|
54
45
|
|
55
46
|
def enq(session)
|
56
|
-
@
|
57
|
-
@queue.enq [session, Time.now]
|
47
|
+
@queue.enq session
|
58
48
|
end
|
59
49
|
|
60
50
|
def try_create
|
61
51
|
@mutex.synchronize do
|
62
|
-
return unless @created < size
|
63
|
-
|
64
|
-
session = Xlogin.get(@args, **@opts)
|
65
|
-
update_watchdog(session)
|
52
|
+
return unless @created < @size
|
66
53
|
|
67
54
|
@created += 1
|
68
|
-
|
55
|
+
Xlogin.get(@args, **@opts)
|
69
56
|
end
|
70
57
|
end
|
71
58
|
|
72
|
-
def update_watchdog(session)
|
73
|
-
return unless idle
|
74
|
-
|
75
|
-
@watchdog[session].tap { |th| th.kill if th }
|
76
|
-
@watchdog[session] = Thread.new(session) { |s| sleep(idle.to_f + 1) && s.close }
|
77
|
-
end
|
78
59
|
end
|
79
60
|
|
80
61
|
end
|
data/lib/xlogin/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xlogin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- haccht
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-telnet
|