xlogin 0.9.0 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|