xlogin 0.8.3 → 0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/xlogin/cli.rb +83 -36
- 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: d0c4789d65178ce5f60077b6d9f1f066872a7e8f
|
4
|
+
data.tar.gz: d41b0cdf51f5a566c84757104cb5094e1504ba1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9b3b1cf81d0f967cfaa2cfb3d630f1e1e1ede4abd3c5671b3b85eec429a5f5f6b088cf0fe763a61f6e8b1c6c977baa0b227f522465d38028347099fb47f3ca5
|
7
|
+
data.tar.gz: 3005ee45108fc3c5f61b0c2abf0c77916db5a0561508274a9e9c4498d4c3dc7cc529136d3cf35f95a82ab6152f3c9c131772e952dc04ed85d5c74dfb5e6f355e
|
data/Gemfile.lock
CHANGED
data/lib/xlogin/cli.rb
CHANGED
@@ -4,6 +4,7 @@ require 'optparse'
|
|
4
4
|
require 'ostruct'
|
5
5
|
require 'parallel'
|
6
6
|
require 'readline'
|
7
|
+
require 'socket'
|
7
8
|
require 'stringio'
|
8
9
|
|
9
10
|
module Xlogin
|
@@ -20,13 +21,15 @@ module Xlogin
|
|
20
21
|
|
21
22
|
def self.getopts(args)
|
22
23
|
config = OpenStruct.new(
|
23
|
-
|
24
|
+
jobs: 1,
|
25
|
+
port: 8080,
|
26
|
+
taskname: :tty,
|
24
27
|
inventory: nil,
|
25
28
|
templates: [],
|
26
29
|
)
|
27
30
|
|
28
31
|
parser = OptionParser.new
|
29
|
-
parser.banner = "#{File.basename($0)}
|
32
|
+
parser.banner = "#{File.basename($0)} HOST_PATTERN [Options]"
|
30
33
|
parser.version = Xlogin::VERSION
|
31
34
|
|
32
35
|
parser.on('-i PATH', '--inventory', String, 'The PATH to the inventory file(default: $HOME/.xloginrc).') { |v| config.inventory = v }
|
@@ -34,14 +37,20 @@ module Xlogin
|
|
34
37
|
parser.on('-T DIRECTORY', '--template-dir', String, 'The DIRECTORY of the template files.') { |v| config.templates += Dir.glob(File.join(v, '*.rb')) }
|
35
38
|
parser.on('-L [DIRECTORY]', '--log-dir', String, 'The DIRECTORY of the log files(default: $PWD).') { |v| config.logdir = v || '.' }
|
36
39
|
|
37
|
-
parser.on('-
|
38
|
-
parser.on('-e',
|
40
|
+
parser.on('-l', '--list', TrueClass, 'List all available devices.') { |v| config.taskname = :list }
|
41
|
+
parser.on('-e', '--exec', TrueClass, 'Execute commands and quit.') { |v| config.taskname = :exec }
|
42
|
+
parser.on('-t', '--tty', TrueClass, 'Allocate a pseudo-tty.') { |v| config.taskname = :tty }
|
43
|
+
|
44
|
+
parser.on('-p NUM', '--port', Integer, 'Run as server on specified port(default: 8080).') { |v| config.taskname = :listen; config.port = v }
|
45
|
+
parser.on('-j NUM', '--jobs', Integer, 'The NUM of jobs to execute in parallel(default: 1).') { |v| config.jobs = v }
|
46
|
+
|
47
|
+
parser.on('-E', '--enable', TrueClass, 'Try to gain enable priviledge.') { |v| config.enable = v }
|
39
48
|
parser.on('-y', '--assume-yes', TrueClass, 'Automatically answer yes to prompts.') { |v| config.authorize = v }
|
40
49
|
|
41
50
|
begin
|
42
51
|
args = parser.parse!(args)
|
43
|
-
|
44
|
-
|
52
|
+
host = args.shift
|
53
|
+
config.args = args
|
45
54
|
|
46
55
|
Xlogin.configure do
|
47
56
|
config.inventory ||= DEFAULT_INVENTORY_FILE
|
@@ -55,13 +64,8 @@ module Xlogin
|
|
55
64
|
load_templates(*config.templates.map { |file| File.expand_path(file, ENV['PWD']) })
|
56
65
|
end
|
57
66
|
|
58
|
-
config.hostlist =
|
59
|
-
config.
|
60
|
-
config.arguments = args
|
61
|
-
|
62
|
-
methods = Xlogin::CLI.instance_methods(false)
|
63
|
-
raise "No host found: `#{hostlist}`" if config.hostlist.empty?
|
64
|
-
raise "No task defined: `#{taskname}`" if config.taskname.empty? || methods.find_index(config.taskname.to_sym).nil?
|
67
|
+
config.hostlist = host.to_s.split(',').flat_map { |pattern| Xlogin.factory.list(pattern) }
|
68
|
+
raise "No host found: `#{host}`" if config.hostlist.empty?
|
65
69
|
rescue => e
|
66
70
|
$stderr.puts e, '', parser
|
67
71
|
exit 1
|
@@ -71,55 +75,98 @@ module Xlogin
|
|
71
75
|
end
|
72
76
|
|
73
77
|
def list(config)
|
74
|
-
|
75
|
-
|
78
|
+
wid1 = config.hostlist.map { |e| e[:name].length }.max
|
79
|
+
wid2 = config.hostlist.map { |e| e[:type].length }.max
|
80
|
+
list = config.hostlist.map { |e| "#{e[:name].to_s.ljust(wid1)} #{e[:type].to_s.ljust(wid2)} #{e[:uri]}" }.sort
|
81
|
+
$stdout.puts list
|
76
82
|
end
|
77
83
|
|
78
84
|
def tty(config)
|
79
85
|
Signal.trap(:INT) { exit 0 }
|
86
|
+
|
80
87
|
list = config.hostlist.sort_by { |e| e[:name] }
|
81
88
|
list.each do |target|
|
82
|
-
|
83
|
-
|
89
|
+
unless list.size == 1
|
90
|
+
case resp = Readline.readline(">> #{target[:name]}(Y/n)? ", false).strip
|
91
|
+
when /^y(es)?$/i, ''
|
92
|
+
when /^n(o)?$/i then next
|
93
|
+
else redo
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
config.jobs = 1
|
84
98
|
config.hostlist = [target]
|
85
|
-
|
99
|
+
|
100
|
+
$stdout.puts "Trying #{target[:name]}...", "Escape character is '^]'."
|
101
|
+
session, _ = exec(config)
|
102
|
+
session.interact!
|
86
103
|
end
|
87
104
|
end
|
88
105
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
106
|
+
def listen(config)
|
107
|
+
Signal.trap(:INT) { exit 0 }
|
108
|
+
config.jobs = config.hostlist.size
|
109
|
+
|
110
|
+
width = config.hostlist.map { |e| e[:name].length }.max
|
111
|
+
sessions = exec(config).compact
|
112
|
+
|
113
|
+
$stdout.puts "", ""
|
114
|
+
$stdout.puts "=> Start xlogin server on port=#{config.port}"
|
115
|
+
$stdout.puts "=> Ctrl-C to shutdown"
|
116
|
+
|
117
|
+
server = TCPServer.open(config.port)
|
118
|
+
socket = server.accept
|
119
|
+
while line = socket.gets
|
120
|
+
Parallel.each(sessions, in_threads: sessions.size) do |session|
|
121
|
+
resp = session.cmd(line.chomp)
|
122
|
+
prefix = "#{session.name.to_s.ljust(width)} |"
|
123
|
+
output = resp.to_s.lines.map { |line| prefix + line.chomp.gsub("\r", '') + "\n" }.join
|
124
|
+
socket.print output
|
125
|
+
$stdout.print output if config.jobs > 1
|
126
|
+
end
|
127
|
+
end
|
128
|
+
ensure
|
129
|
+
socket.close if socket
|
130
|
+
server.close if server
|
92
131
|
end
|
93
132
|
|
94
|
-
def
|
95
|
-
|
96
|
-
|
97
|
-
|
133
|
+
def exec(config, &block)
|
134
|
+
width = config.hostlist.map { |e| e[:name].length }.max
|
135
|
+
|
136
|
+
Parallel.map(config.hostlist, in_threads: config.jobs) do |hostinfo|
|
137
|
+
session = nil
|
138
|
+
error = nil
|
98
139
|
|
99
|
-
private
|
100
|
-
def login(config, &block)
|
101
|
-
Parallel.map(config.hostlist, in_threads: config.parallel) do |hostinfo|
|
102
140
|
begin
|
103
141
|
buffer = StringIO.new
|
104
142
|
hostname = hostinfo[:name]
|
105
143
|
|
106
144
|
loggers = []
|
107
|
-
loggers << ((config.
|
145
|
+
loggers << ((config.jobs > 1)? buffer : $stdout)
|
108
146
|
loggers << File.expand_path(File.join(config.logdir, "#{hostname}.log"), ENV['PWD']) if config.logdir
|
109
147
|
|
110
148
|
session = Xlogin.get(hostinfo.merge(log: loggers))
|
111
149
|
session.enable if config.enable && hostinfo[:enable]
|
112
150
|
|
113
|
-
|
151
|
+
command_lines = ['', *config.args.flat_map { |e| e.split(';') }].map(&:strip)
|
152
|
+
command_lines.each { |line| session.cmd(line) }
|
153
|
+
|
154
|
+
block.call(session) if block
|
114
155
|
rescue => e
|
115
|
-
|
116
|
-
|
117
|
-
|
156
|
+
error = e
|
157
|
+
ensure
|
158
|
+
if config.jobs > 1
|
159
|
+
prefix = "#{hostname.to_s.ljust(width)} |"
|
160
|
+
output = buffer.string.lines.map { |line| prefix + line.chomp.gsub("\r", '') + "\n" }.join
|
161
|
+
$stdout.print output
|
162
|
+
$stderr.print prefix + "[Error] #{error}\n" if error
|
163
|
+
else
|
164
|
+
$stderr.print "[Error] #{error}\n" if error
|
165
|
+
end
|
118
166
|
|
119
|
-
if config.parallel > 1
|
120
|
-
lines = buffer.string.lines.map { |line| "#{hostname}\t| " + line.gsub("\r", '') }
|
121
|
-
lines.each { |line| $stdout.print "#{line.chomp}\n" }
|
122
167
|
end
|
168
|
+
|
169
|
+
session
|
123
170
|
end
|
124
171
|
end
|
125
172
|
|
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.8.
|
4
|
+
version: 0.8.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- haccht
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-telnet
|