xlogin 0.13.11 → 0.14.1
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 +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