xlogin 0.13.11 → 0.14.1
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 +2 -2
- data/lib/xlogin/cli.rb +10 -10
- data/lib/xlogin/factory.rb +35 -3
- data/lib/xlogin/rake_task.rb +2 -2
- data/lib/xlogin/session.rb +8 -29
- data/lib/xlogin/session_pool.rb +3 -3
- data/lib/xlogin/template.rb +3 -3
- data/lib/xlogin/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bbc5c0255a1328038a84dc96b4e99c1b252c998ece79c03f7e23d22b7c5eba2d
|
4
|
+
data.tar.gz: a605c1f6a0bb730e3aab19c13401c902416aee1e985a34a4d3132c014bc36f43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c077a17025b8131927de93b9602bc1d8957f4545b38bf2ec58c95d460faf3320d55770c8efc65cce4796eeb11fa5d3e4d3bcd7acbd9b35b44e7beffc1da55b5e
|
7
|
+
data.tar.gz: 665cb8e5a6ebde87623135a31ca21d5f2e25408e31e4fc12560fa4ce6095459a686a32317c1a0dabb4eace83224b828999be069a5c84f225fa4dad9dc174a44b
|
data/lib/xlogin.rb
CHANGED
@@ -61,14 +61,14 @@ module Xlogin
|
|
61
61
|
def generate_templates(dir)
|
62
62
|
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
63
63
|
builtin_templates = Dir.glob(File.join(File.dirname(__FILE__), 'xlogin', 'templates', '*.rb'))
|
64
|
-
builtin_templates.each
|
64
|
+
builtin_templates.each{ |file| FileUtils.cp(file, DEFAULT_TEMPLATE_DIR) }
|
65
65
|
end
|
66
66
|
|
67
|
-
private
|
68
67
|
def factory
|
69
68
|
@factory ||= Xlogin::Factory.instance
|
70
69
|
end
|
71
70
|
|
71
|
+
private
|
72
72
|
def set(opts = {})
|
73
73
|
@settings ||= {}
|
74
74
|
opts.each do |key, val|
|
data/lib/xlogin/cli.rb
CHANGED
@@ -15,7 +15,7 @@ module Xlogin
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def list(config)
|
18
|
-
puts Xlogin.list(*config[:pattern]).map
|
18
|
+
puts Xlogin.list(*config[:pattern]).map{ |e| e[:name] }.sort.uniq
|
19
19
|
end
|
20
20
|
|
21
21
|
def tty(config)
|
@@ -26,11 +26,11 @@ module Xlogin
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def exec(config)
|
29
|
-
Signal.trap(:INT)
|
29
|
+
Signal.trap(:INT){ exit 0 }
|
30
30
|
|
31
31
|
jobs = config[:jobs] || 1
|
32
32
|
hosts = Xlogin.list(*config[:pattern])
|
33
|
-
width = hosts.map
|
33
|
+
width = hosts.map{ |e| e[:name].length }.max
|
34
34
|
|
35
35
|
Parallel.map(hosts, in_threads: jobs) do |info|
|
36
36
|
buffer = StringIO.new
|
@@ -43,14 +43,14 @@ module Xlogin
|
|
43
43
|
loggers << File.expand_path(File.join(config[:"log-dir"], "#{info[:name]}.log"), ENV['PWD']) if config[:"log-dir"]
|
44
44
|
|
45
45
|
session = Xlogin.get(info.merge(log: loggers))
|
46
|
-
session.enable(
|
46
|
+
session.enable(session.config.enable) if session.config.enable && Xlogin.settings.enable?
|
47
47
|
|
48
48
|
command_lines = ['', *config[:exec].to_s.split(';').map(&:strip)]
|
49
|
-
command_lines.each
|
49
|
+
command_lines.each{ |line| session.cmd(line) }
|
50
50
|
|
51
|
-
buffer.string.lines.each
|
51
|
+
buffer.string.lines.each{ |line| print prefix + line.gsub("\r", '') } if jobs > 1
|
52
52
|
rescue => e
|
53
|
-
buffer.string.lines.each
|
53
|
+
buffer.string.lines.each{ |line| print prefix + line.gsub("\r", '') } if jobs > 1
|
54
54
|
raise e
|
55
55
|
end
|
56
56
|
|
@@ -71,10 +71,10 @@ module Xlogin
|
|
71
71
|
|
72
72
|
parser.on('-i PATH', '--inventory', String, 'The PATH to the inventory file.')
|
73
73
|
parser.on('-t PATH', '--template', String, 'The PATH to the template file or directory.')
|
74
|
-
parser.on('-L PATH', '--log-dir', String, 'The PATH to the log directory.')
|
74
|
+
parser.on('-L PATH', '--log-dir', String, 'The PATH to the log directory.'){ |v| v || '.' }
|
75
75
|
|
76
|
-
parser.on('-l', '--list', TrueClass, 'List the inventory.')
|
77
|
-
parser.on('-e COMMAND', '--exec', String, 'Execute commands and quit.')
|
76
|
+
parser.on('-l', '--list', TrueClass, 'List the inventory.') { |v| config[:runner] = self.method(:list) }
|
77
|
+
parser.on('-e COMMAND', '--exec', String, 'Execute commands and quit.'){ |v| config[:runner] = self.method(:exec); v }
|
78
78
|
|
79
79
|
parser.on('-E KEY=VAL', '--env', /(\w+=\w+)+/, 'Environment variables.')
|
80
80
|
parser.on('-j NUM', '--jobs', Integer, 'The NUM of jobs to execute in parallel.')
|
data/lib/xlogin/factory.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'addressable/uri'
|
2
2
|
require 'singleton'
|
3
|
+
require 'thread'
|
3
4
|
require 'xlogin/session_pool'
|
4
5
|
require 'xlogin/template'
|
5
6
|
|
@@ -9,8 +10,10 @@ module Xlogin
|
|
9
10
|
include Singleton
|
10
11
|
|
11
12
|
def initialize
|
12
|
-
@inventory
|
13
|
-
@templates
|
13
|
+
@inventory = Hash.new
|
14
|
+
@templates = Hash.new
|
15
|
+
@gateways = Hash.new
|
16
|
+
@mutex = Mutex.new
|
14
17
|
end
|
15
18
|
|
16
19
|
def set_inventory(name, **opts)
|
@@ -28,7 +31,7 @@ module Xlogin
|
|
28
31
|
values2 = pattern.split(',').map do |entry|
|
29
32
|
key, val = entry.to_s.split(':')
|
30
33
|
key, val = 'name', key if val.nil?
|
31
|
-
@inventory.values.select
|
34
|
+
@inventory.values.select{ |e| File.fnmatch(val, e[key.to_sym]) }
|
32
35
|
end
|
33
36
|
values2.reduce(&:&)
|
34
37
|
end
|
@@ -50,6 +53,35 @@ module Xlogin
|
|
50
53
|
@templates.keys
|
51
54
|
end
|
52
55
|
|
56
|
+
def open_tunnel(tunnel, host, port)
|
57
|
+
@mutex.synchronize do
|
58
|
+
unless @gateways[tunnel]
|
59
|
+
gateway_uri = Addressable::URI.parse(tunnel)
|
60
|
+
case gateway_uri.scheme
|
61
|
+
when 'ssh'
|
62
|
+
username, password = *gateway_uri.userinfo.split(':')
|
63
|
+
@gateways[tunnel] = Net::SSH::Gateway.new(
|
64
|
+
gateway_uri.host,
|
65
|
+
username,
|
66
|
+
password: password,
|
67
|
+
port: gateway_uri.port || 22
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
gateway = @gateways[tunnel]
|
73
|
+
return host, port unless gateway
|
74
|
+
return '127.0.0.1', gateway.open(host, port)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def close_tunnel(tunnel, port)
|
79
|
+
@mutex.synchronize do
|
80
|
+
gateway = @gateways[tunnel]
|
81
|
+
gateway.close(port) if gateway
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
53
85
|
def build(type:, **opts)
|
54
86
|
template = get_template(type)
|
55
87
|
raise Xlogin::Error.new("Template not found: '#{type}'") unless template
|
data/lib/xlogin/rake_task.rb
CHANGED
@@ -13,7 +13,7 @@ module Xlogin
|
|
13
13
|
|
14
14
|
def generate(*patterns, **opts, &block)
|
15
15
|
description = Rake.application.last_description
|
16
|
-
hostnames = Xlogin.list(*patterns).map
|
16
|
+
hostnames = Xlogin.list(*patterns).map{ |e| e[:name] }
|
17
17
|
|
18
18
|
task 'all' => hostnames unless opts[:all] == false
|
19
19
|
hostnames.each do |hostname|
|
@@ -111,7 +111,7 @@ module Xlogin
|
|
111
111
|
end
|
112
112
|
|
113
113
|
module SessionModule
|
114
|
-
def
|
114
|
+
def log_message(text, prefix: "[INFO]", chomp: false, **color)
|
115
115
|
default_color = { color: :green }
|
116
116
|
|
117
117
|
log("\n")
|
data/lib/xlogin/session.rb
CHANGED
@@ -22,16 +22,16 @@ module Xlogin
|
|
22
22
|
end
|
23
23
|
|
24
24
|
@name = opts[:name] || @host
|
25
|
+
@tunnel = opts[:tunnel] || opts[:via]
|
25
26
|
@config = ReadOnlyStruct.new(opts)
|
26
27
|
@template = template
|
27
28
|
@username, @password = uri.userinfo.to_s.split(':')
|
28
29
|
|
29
|
-
forward = @config.forward || @config.via
|
30
|
-
ssh_tunnel(forward) if forward
|
31
30
|
max_retry = @config.retry || 1
|
31
|
+
@host, @port = Xlogin.factory.open_tunnel(@tunnel, @host, @port) if @tunnel
|
32
32
|
|
33
33
|
@mutex = Mutex.new
|
34
|
-
@loggers = [@config.log].flatten.uniq.reduce({})
|
34
|
+
@loggers = [@config.log].flatten.uniq.reduce({}){ |a, e| a.merge(e => build_logger(e)) }
|
35
35
|
|
36
36
|
begin
|
37
37
|
args = Hash.new
|
@@ -73,13 +73,13 @@ module Xlogin
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def puts(*args, &block)
|
76
|
-
args = args.flat_map
|
76
|
+
args = args.flat_map{ |arg| instance_exec(arg, &@template.interrupt!) }.compact if @template.interrupt!
|
77
77
|
args.empty? ? super('', &block) : super(*args, &block)
|
78
78
|
end
|
79
79
|
|
80
80
|
def waitfor(*args, &block)
|
81
81
|
args = [prompt_pattern] if args.empty?
|
82
|
-
@mutex.synchronize
|
82
|
+
@mutex.synchronize{ _waitfor(*args, &block) }
|
83
83
|
end
|
84
84
|
|
85
85
|
def close
|
@@ -90,17 +90,13 @@ module Xlogin
|
|
90
90
|
logger.close
|
91
91
|
end
|
92
92
|
|
93
|
-
if @
|
94
|
-
@gateway.close(@port)
|
95
|
-
@gateway.shutdown!
|
96
|
-
end
|
97
|
-
|
93
|
+
Xlogin.factory.close_tunnel(@tunnel, @port) if @tunnel
|
98
94
|
super
|
99
95
|
end
|
100
96
|
end
|
101
97
|
|
102
98
|
def log(text)
|
103
|
-
@loggers.each
|
99
|
+
@loggers.each{ |_, logger| logger.syswrite(text) if logger }
|
104
100
|
end
|
105
101
|
|
106
102
|
def enable_log(log = $stdout)
|
@@ -127,7 +123,7 @@ module Xlogin
|
|
127
123
|
block.call(recv) if block
|
128
124
|
end
|
129
125
|
|
130
|
-
_, process = @template.prompt.find
|
126
|
+
_, process = @template.prompt.find{ |r, p| r =~ line && p }
|
131
127
|
if process
|
132
128
|
instance_eval(&process)
|
133
129
|
line += _waitfor(*args, &block)
|
@@ -136,23 +132,6 @@ module Xlogin
|
|
136
132
|
return line
|
137
133
|
end
|
138
134
|
|
139
|
-
def ssh_tunnel(gateway)
|
140
|
-
gateway_uri = Addressable::URI.parse(gateway)
|
141
|
-
case gateway_uri.scheme
|
142
|
-
when 'ssh'
|
143
|
-
username, password = *gateway_uri.userinfo.split(':')
|
144
|
-
@gateway = Net::SSH::Gateway.new(
|
145
|
-
gateway_uri.host,
|
146
|
-
username,
|
147
|
-
password: password,
|
148
|
-
port: gateway_uri.port || 22
|
149
|
-
)
|
150
|
-
|
151
|
-
@port = @gateway.open(@host, @port)
|
152
|
-
@host = '127.0.0.1'
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
135
|
def build_logger(log)
|
157
136
|
case log
|
158
137
|
when String
|
data/lib/xlogin/session_pool.rb
CHANGED
@@ -22,16 +22,16 @@ module Xlogin
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def size=(val)
|
25
|
-
@mutex.synchronize
|
25
|
+
@mutex.synchronize{ @size = val }
|
26
26
|
end
|
27
27
|
|
28
28
|
def idle=(val)
|
29
|
-
@mutex.synchronize
|
29
|
+
@mutex.synchronize{ @idle = val }
|
30
30
|
end
|
31
31
|
|
32
32
|
def with
|
33
33
|
session = deq
|
34
|
-
Thread.handle_interrupt(Exception => :immediate)
|
34
|
+
Thread.handle_interrupt(Exception => :immediate){ yield session }
|
35
35
|
ensure
|
36
36
|
enq session
|
37
37
|
end
|
data/lib/xlogin/template.rb
CHANGED
@@ -47,12 +47,12 @@ module Xlogin
|
|
47
47
|
klass = Class.new(Xlogin.const_get(uri.scheme.capitalize))
|
48
48
|
klass.class_exec(self) do |template|
|
49
49
|
scopes = [*opts[:scope]].compact
|
50
|
-
scopes.each
|
50
|
+
scopes.each{ |scope| template.instance_eval(&template.scopes[scope]) }
|
51
51
|
|
52
52
|
template.methods.each do |name, block|
|
53
53
|
case name.to_s
|
54
54
|
when 'enable'
|
55
|
-
define_method(name)
|
55
|
+
define_method(name){ |args = nil| instance_exec(args || opts[:enable], &block) }
|
56
56
|
else
|
57
57
|
define_method(name, &block)
|
58
58
|
end
|
@@ -64,7 +64,7 @@ module Xlogin
|
|
64
64
|
|
65
65
|
def method_missing(name, *, &block)
|
66
66
|
super unless RESERVED_METHODS.include?(name)
|
67
|
-
bind(name)
|
67
|
+
bind(name){ |*args| instance_exec(*args, &block) }
|
68
68
|
end
|
69
69
|
|
70
70
|
end
|
data/lib/xlogin/version.rb
CHANGED