xlogin 0.8.3 → 0.8.4
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/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
|