xlogin 0.10.9 → 0.11.0

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