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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21cb559588f816c0f1497df58f3f3dfe819943e8
4
- data.tar.gz: f7742b32f267dddad2afa23cdd0a7928e2a6c589
3
+ metadata.gz: 7920c6bfed2e33fd3aa7e60128ae9b01b2464dec
4
+ data.tar.gz: 6304076fbb457c60020f8fd8875ea147bd162d85
5
5
  SHA512:
6
- metadata.gz: 92d5465fa016af9b0a93338c6826741d75fe153a1c0ad6fb567ee5a89a9e5f658e977d3112d99d17eb6644db33b358e3705c158f6a79238e99d8c54d609a2b7c
7
- data.tar.gz: afe1f174a3e785a8ee8d1d2bcc09d63478e804f1f698f8615611c95c8efa59ca84c2a77d88b0c197b1f6142a95d0aa1495fc379ce202528dad12ba9661742072
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.list_info(*patterns)
30
+ factory.list_inventory(*patterns)
31
31
  end
32
32
 
33
33
  def get_pool(args, **opts, &block)
34
- pool = Xlogin::SessionPool.new(args, **opts)
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.set_info(**args)
60
+ factory.set_inventory(**args)
61
61
  end
62
62
 
63
63
  def source(*source_files)
@@ -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.get_info(target_host)
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
 
@@ -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 set_info(**opts)
15
- name = opts[:name]
16
- return unless name
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 get_info(name)
20
+ def get_inventory(name)
21
21
  @inventory[name]
22
22
  end
23
23
 
24
- def list_info(*patterns)
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:, uri:, **opts)
50
+ def build(type:, **opts)
51
51
  template = get_template(type)
52
- template.build(uri, **opts)
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(hostname, **opts)
56
- hostinfo = get_info(hostname)
57
- raise SessionError.new("Host not found: '#{hostname}'") unless hostinfo
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
- build(hostinfo.merge(name: hostname, **opts))
71
+ def build_pool(args, **opts)
72
+ Xlogin::SessionPool.new(args, **opts)
60
73
  end
61
74
 
62
75
  end
@@ -23,7 +23,7 @@ module Xlogin
23
23
 
24
24
  raise SessionError.new("Invalid URI - '#{uri}'") unless @host && @port
25
25
 
26
- @name = opts.delete(:name) || @host
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 = Mutex.new
35
- @closed = false
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 cmd(*args, &block)
65
- @mutex.synchronize { super(*args, &block) }
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
- args << Regexp.union(*@template.prompt.map(&:first)) if args.empty?
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
- @output_loggers.each do |output_log, logger|
94
- next unless logger
95
- logger.close if output_log.kind_of?(String)
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 closed?
105
- @closed
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
- @output_loggers = build_loggers
90
+ disable_log(log)
117
91
  end
118
92
  end
119
93
 
120
- def disable_log(out = $stdout)
121
- @output_loggers = build_loggers(@output_logs - [out])
94
+ def disable_log(log = $stdout)
95
+ @loggers.delete(log)
122
96
  if block_given?
123
97
  yield
124
- @output_loggers = build_loggers
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
- @output_loggers.each do |_, logger|
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 build_loggers(output_logs = @output_logs)
154
- [output_logs].flatten.uniq.each.with_object({}) do |output_log, loggers|
155
- case output_log
156
- when String
157
- FileUtils.mkdir_p(File.dirname(output_log))
158
- loggers[output_log] = File.open(output_log, 'a+').tap do |logger|
159
- logger.binmode
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
@@ -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 = args
12
- @opts = 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
- Thread.handle_interrupt(Exception => :immediate) { yield session }
39
- ensure
40
- enq(session)
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
- @mutex.synchronize { update_watchdog(session) }
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
- session
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
@@ -1,3 +1,3 @@
1
1
  module Xlogin
2
- VERSION = "0.9.0"
2
+ VERSION = "0.9.2"
3
3
  end
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.0
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-15 00:00:00.000000000 Z
11
+ date: 2018-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-telnet