xlogin 0.4.13 → 0.4.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a84117cf243901542377439588814867063f606f
4
- data.tar.gz: 9ae1b629e907bb8d098e675c614b448f8cc441cb
3
+ metadata.gz: 6d941fe4495b8ed1f28b816a25771e8eb5bf54c6
4
+ data.tar.gz: 33099f53dc53986179ce61f340a7109e27e2488b
5
5
  SHA512:
6
- metadata.gz: f9f5ca361ced4a41f624be0dcd397b1d0840be0e7f74dd7ce12a42c9f52ca4e8f64f1606c6d009a2aca272976a10e4db325f1ff04f3b471382138029c11cf2de
7
- data.tar.gz: 97d1d8831eb885401d4afec33c9e0c7bb85a7e40070fbd6d567b63043523f781be4c225866ed052a0932f9c3ea166cdf0e2ebb623755815dcf48f6de24bba730
6
+ metadata.gz: eb5634e09f8267227e0302367f44452c330bb7cd06152f2550574d28075398e58482b0bd49ff67baca7b807a3af2ac85c66a78dda7ed72272adf8e5ada93845f
7
+ data.tar.gz: 95c7b3a2a772dc46971d42ee32d0da759317a8abf8769966c6b8fa324353917166ef7f4fa682aa35c8990246502a528ab1cb3d22c10aa3a2ce4dae37d1387de7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- xlogin (0.4.13)
4
+ xlogin (0.4.14)
5
5
  net-ssh
6
6
  net-ssh-gateway
7
7
  net-ssh-telnet
data/bin/cmd_exec CHANGED
@@ -1,123 +1,10 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
- require 'optparse'
4
- require 'readline'
5
- require 'stringio'
6
- require 'thread'
7
3
  require 'xlogin'
4
+ require 'xlogin/cli'
8
5
 
9
- module Xlogin
6
+ PLUGIN_TEMPLATES = Dir.glob(File.join(File.dirname(__FILE__), 'templates', '*.rb'))
7
+ Xlogin.load_templates(*PLUGIN_TEMPLATES)
10
8
 
11
- class ThreadPool
12
-
13
- def initialize(size)
14
- @jobs = Array.new
15
- @lock = Queue.new
16
-
17
- @size = size
18
- @size.times { @lock.push :token }
19
-
20
- begin yield(self) ensure join end if block_given?
21
- end
22
-
23
- def run
24
- @jobs << Thread.new do
25
- token = @lock.pop
26
- yield
27
- @lock.push token
28
- end
29
- end
30
-
31
- def join
32
- @jobs.each { |job| job.join }
33
- end
34
-
35
- end
36
-
37
- class CLI
38
-
39
- def self.getopts(args)
40
- options = Hash.new
41
-
42
- opt = OptionParser.new
43
- opt.on('-F', '--force', 'Automatically reply "yes" if confirmed.') { |v| options[:F] = v }
44
- opt.on('-e', '--enable', 'Try to gain enable priviledge.') { |v| options[:e] = v }
45
- opt.on('-l', '--log', 'Enable logging.') { |v| options[:l] = v }
46
- opt.on('-H', 'Display hostnames for each response.') { |v| options[:H] = v }
47
-
48
- opt.on('-f FILE', 'Read target hostnames from FILE.') { |v| options[:f] = v }
49
-
50
- opt.on('-x VALUE', 'Read commands from VALUE.') { |v| options[:x] = v }
51
- opt.on('-c VALUE') { |v| options[:c] = v }
52
-
53
- opt.on('-p VALUE', 'Specify concurrency pool size.') { |v| options[:p] = v }
54
- opt.on('-i VALUE', 'Specify interval time [sec].') { |v| options[:i] = v }
55
-
56
- opt.banner += ' HOST...'
57
- opt.summary_width = 16
58
-
59
- self.class.module_eval do
60
- define_method(:usage) do |msg = nil|
61
- puts opt.to_s
62
- puts "error: #{msg}" if msg
63
- exit 1
64
- end
65
- end
66
-
67
- opt.parse!(args)
68
- return options, args
69
- end
70
-
71
- def self.run(args = ARGV)
72
- options, args = getopts(args)
73
- usage if options[:x].nil? and options[:c].nil?
74
- usage if options[:f].nil? && args.empty?
75
-
76
- source_dirs = [ENV['HOME'], Dir.pwd]
77
- source_files = source_dirs.flat_map { |dir| [File.join(dir, '_xloginrc'), File.join(dir, '.xloginrc')] }
78
- Xlogin.factory.source(*source_files)
79
-
80
- size = (options[:p] || 1).to_i
81
- interval = (options[:i] || 0).to_i
82
- commands = ((options[:x] == '-') ? $stdin.read : options[:x]).split(/[;\n]/) if options[:x]
83
-
84
- nodes = args.dup
85
- nodes += IO.readlines(options[:f]).map(&:chomp) if options[:f]
86
-
87
- ThreadPool.new(size) do |pool|
88
- nodes.each do |node|
89
- next if node =~ /^\s*#/
90
-
91
- pool.run do
92
- begin
93
- resp = StringIO.new
94
- force = options[:F] || false
95
- loggers = []
96
- loggers << $stdout unless size > 1
97
- loggers << (URI.regexp =~ node ? URI(node).host : node) + ".log" if options[:l]
98
-
99
-
100
- session = Xlogin.get(node, force: force, log: loggers)
101
- session.enable if options[:e] && session.respond_to?(:enable)
102
-
103
- if options[:x]
104
- ['', *commands].map { |command| resp.print session.cmd(command) }
105
- elsif options[:c]
106
- resp.puts session.send(options[:c].to_sym)
107
- end
108
-
109
- content = resp.string
110
- content = content.lines.map { |line| "#{node}: #{line}" }.join if options[:H]
111
-
112
- $stdout.puts content if size > 1
113
- rescue => e
114
- $stderr.puts "Something goes wrong with '#{node}' - #{e}"
115
- end
116
- end
117
- end
118
- end
119
- end
120
- end
121
- end
122
-
123
- Xlogin::CLI.run if $0 == __FILE__
9
+ Xlogin.source
10
+ Xlogin::ExecCLI.run
data/bin/xlogin CHANGED
@@ -1,64 +1,10 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
- require 'optparse'
4
- require 'readline'
5
3
  require 'xlogin'
4
+ require 'xlogin/cli'
6
5
 
7
- module Xlogin
8
- class CLI
9
- def self.getopts(args)
10
- options = Hash.new
6
+ PLUGIN_TEMPLATES = Dir.glob(File.join(File.dirname(__FILE__), 'templates', '*.rb'))
7
+ Xlogin.load_templates(*PLUGIN_TEMPLATES)
11
8
 
12
- opt = OptionParser.new
13
- opt.on('-e', '--enable', 'Try to gain enable priviledge.') { |v| options[:e] = v }
14
- opt.on('-l', '--log', 'Enable logging.') { |v| options[:l] = v }
15
-
16
- opt.on( '--list', 'List all devices.') { |v| options[:list] = v }
17
-
18
- opt.banner += ' HOST'
19
- opt.summary_width = 16
20
-
21
- self.class.module_eval do
22
- define_method(:usage) do |msg = nil|
23
- puts opt.to_s
24
- puts "error: #{msg}" if msg
25
- exit 1
26
- end
27
- end
28
-
29
- opt.parse!(args)
30
- return options, args
31
- end
32
-
33
- def self.run(args = ARGV)
34
- options, args = getopts(args)
35
-
36
- source_dirs = [ENV['HOME'], Dir.pwd]
37
- source_files = source_dirs.flat_map { |dir| [File.join(dir, '_xloginrc'), File.join(dir, '.xloginrc')] }
38
- Xlogin.factory.source(*source_files)
39
-
40
- if options[:list]
41
- puts Xlogin.factory.list.map { |e| "#{e[:name]}\t#{e[:type]}" }
42
- exit 0
43
- end
44
-
45
- target = args.shift
46
- usage unless target
47
-
48
- loggers = [$stdout]
49
- loggers.push("#{target}.log") if options[:l]
50
-
51
- puts "Trying #{target}..."
52
- puts "Escape character is '^]'."
53
-
54
- session = Xlogin.get(target, force_grant: options[:e], log: loggers)
55
- session.interact!
56
- rescue => e
57
- $stderr.puts("#{e}\n\n")
58
- raise
59
- end
60
-
61
- end
62
- end
63
-
64
- Xlogin::CLI.run if $0 == __FILE__
9
+ Xlogin.source
10
+ Xlogin::CLI.run
data/lib/xlogin/cli.rb ADDED
@@ -0,0 +1,168 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'readline'
5
+ require 'stringio'
6
+ require 'thread'
7
+
8
+ module Xlogin
9
+
10
+ class ThreadPool
11
+
12
+ def initialize(size)
13
+ @jobs = Array.new
14
+ @lock = Queue.new
15
+
16
+ @size = size
17
+ @size.times { @lock.push :token }
18
+
19
+ begin yield(self) ensure join end if block_given?
20
+ end
21
+
22
+ def run
23
+ @jobs << Thread.new do
24
+ token = @lock.pop
25
+ yield
26
+ @lock.push token
27
+ end
28
+ end
29
+
30
+ def join
31
+ @jobs.each { |job| job.join }
32
+ end
33
+
34
+ end
35
+
36
+ class CLI
37
+
38
+ def self.getopts(args)
39
+ options = Hash.new
40
+
41
+ opt = OptionParser.new
42
+ opt.on('-e', '--enable', 'Try to gain enable priviledge.') { |v| options[:e] = v }
43
+ opt.on('-l', '--log', 'Enable logging.') { |v| options[:l] = v }
44
+
45
+ opt.on( '--list', 'List all devices.') { |v| options[:list] = v }
46
+
47
+ opt.banner += ' HOST'
48
+ opt.summary_width = 16
49
+
50
+ self.class.module_eval do
51
+ define_method(:usage) do |msg = nil|
52
+ puts opt.to_s
53
+ puts "error: #{msg}" if msg
54
+ exit 1
55
+ end
56
+ end
57
+
58
+ opt.parse!(args)
59
+ return options, args
60
+ end
61
+
62
+ def self.run(args = ARGV)
63
+ options, args = getopts(args)
64
+
65
+ if options[:list]
66
+ puts Xlogin.factory.list.map { |e| "#{e[:name]}\t#{e[:type]}" }
67
+ exit 0
68
+ end
69
+
70
+ target = args.shift
71
+ usage unless target
72
+
73
+ loggers = [$stdout]
74
+ loggers.push("#{target}.log") if options[:l]
75
+
76
+ puts "Trying #{target}..."
77
+ puts "Escape character is '^]'."
78
+
79
+ session = Xlogin.get(target, force_grant: options[:e], log: loggers)
80
+ session.interact!
81
+ rescue => e
82
+ $stderr.puts("#{e}\n\n")
83
+ raise
84
+ end
85
+
86
+ end
87
+
88
+ class ExecCLI
89
+
90
+ def self.getopts(args)
91
+ options = Hash.new
92
+
93
+ opt = OptionParser.new
94
+ opt.on('-F', '--force', 'Automatically reply "yes" if confirmed.') { |v| options[:F] = v }
95
+ opt.on('-e', '--enable', 'Try to gain enable priviledge.') { |v| options[:e] = v }
96
+ opt.on('-l', '--log', 'Enable logging.') { |v| options[:l] = v }
97
+ opt.on('-H', 'Display hostnames for each response.') { |v| options[:H] = v }
98
+
99
+ opt.on('-f FILE', 'Read target hostnames from FILE.') { |v| options[:f] = v }
100
+
101
+ opt.on('-x VALUE', 'Read commands from VALUE.') { |v| options[:x] = v }
102
+ opt.on('-c VALUE') { |v| options[:c] = v }
103
+
104
+ opt.on('-p VALUE', 'Specify concurrency pool size.') { |v| options[:p] = v }
105
+ opt.on('-i VALUE', 'Specify interval time [sec].') { |v| options[:i] = v }
106
+
107
+ opt.banner += ' HOST...'
108
+ opt.summary_width = 16
109
+
110
+ self.class.module_eval do
111
+ define_method(:usage) do |msg = nil|
112
+ puts opt.to_s
113
+ puts "error: #{msg}" if msg
114
+ exit 1
115
+ end
116
+ end
117
+
118
+ opt.parse!(args)
119
+ return options, args
120
+ end
121
+
122
+ def self.run(args = ARGV)
123
+ options, args = getopts(args)
124
+ usage if options[:x].nil? and options[:c].nil?
125
+ usage if options[:f].nil? && args.empty?
126
+
127
+ size = (options[:p] || 1).to_i
128
+ interval = (options[:i] || 0).to_i
129
+ commands = ((options[:x] == '-') ? $stdin.read : options[:x]).split(/[;\n]/) if options[:x]
130
+
131
+ nodes = args.dup
132
+ nodes += IO.readlines(options[:f]).map(&:chomp) if options[:f]
133
+
134
+ ThreadPool.new(size) do |pool|
135
+ nodes.each do |node|
136
+ next if node =~ /^\s*#/
137
+
138
+ pool.run do
139
+ begin
140
+ resp = StringIO.new
141
+ force = options[:F] || false
142
+ loggers = []
143
+ loggers << $stdout unless size > 1
144
+ loggers << (URI.regexp =~ node ? URI(node).host : node) + ".log" if options[:l]
145
+
146
+
147
+ session = Xlogin.get(node, force: force, log: loggers)
148
+ session.enable if options[:e] && session.respond_to?(:enable)
149
+
150
+ if options[:x]
151
+ ['', *commands].map { |command| resp.print session.cmd(command) }
152
+ elsif options[:c]
153
+ resp.puts session.send(options[:c].to_sym)
154
+ end
155
+
156
+ content = resp.string
157
+ content = content.lines.map { |line| "#{node}: #{line}" }.join if options[:H]
158
+
159
+ $stdout.puts content if size > 1
160
+ rescue => e
161
+ $stderr.puts "Something goes wrong with '#{node}' - #{e}"
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -53,17 +53,18 @@ module Xlogin
53
53
  end
54
54
 
55
55
  if grant = opts.delete(:grant)
56
- open, password, close = grant.split(':')
57
- klass.class_exec(open, password, close) do |open, password, close|
58
- alias_method "original_#{open}".to_sym, open.to_sym
59
- define_method(open) do |arg = password, &block|
60
- send("original_#{open}", arg)
56
+ mod_open, password, mod_close= grant.split(':')
57
+ klass.class_exec(mod_open, password, mod_close) do |mod_open, password, mod_close|
58
+ alias_method "__#{mod_open}".to_sym, mod_open.to_sym
59
+ define_method(mod_open) do |*args, &block|
60
+ args = [*args, password] unless password.empty?
61
+ send("__#{mod_open}", *args)
61
62
  if block
62
63
  block.call
63
- cmd(close)
64
+ cmd(mod_close)
64
65
  end
65
66
  end
66
- alias_method :enable, open
67
+ alias_method :enable, mod_open unless mod_open.to_sym == :enable
67
68
  end
68
69
  end
69
70
 
@@ -39,12 +39,6 @@ module Xlogin
39
39
  end
40
40
 
41
41
  def source(*files)
42
- if files.empty?
43
- files += [ENV['HOME'], Dir.pwd].flat_map do |dir|
44
- [File.join(dir, '_xloginrc'), File.join(dir, '.xloginrc')]
45
- end
46
- end
47
-
48
42
  files.compact.uniq.each do |file|
49
43
  next unless File.exist?(file)
50
44
  instance_eval(IO.read(file))
@@ -64,7 +58,7 @@ module Xlogin
64
58
  end
65
59
 
66
60
  def build(args)
67
- type = args.delete(:type)
61
+ type = args.delete(:type)
68
62
  template = get_template(type)
69
63
  raise Xlogin::GeneralError.new("Template not defined: #{type}") unless template
70
64
 
@@ -72,8 +66,7 @@ module Xlogin
72
66
  opts = args.reduce({}) { |a, (k, v)| a.merge(k.to_s.downcase.to_sym => v) }
73
67
  raise Xlogin::GeneralError.new("Host not found: #{args}") unless uri
74
68
 
75
- session = template.dup.run(uri, opts)
76
- session
69
+ template.dup.run(uri, opts)
77
70
  end
78
71
 
79
72
  def build_from_hostname(hostname, **args)
@@ -13,7 +13,7 @@ module Xlogin
13
13
  @mutex ||= Mutex.new
14
14
  end
15
15
 
16
- def source(file, &block)
16
+ def load(file, &block)
17
17
  Xlogin.factory.source(file)
18
18
  hostnames = Xlogin.factory.list.map { |e| e[:name] }
19
19
  bulk(hostnames, &block)
@@ -13,7 +13,7 @@ module Xlogin
13
13
  @host = @opts[:host]
14
14
  @name = @opts[:name] || @host
15
15
  @port = @opts[:port]
16
- @userinfo = @opts[:userinfo].to_s.split(':')
16
+ @userinfo = @opts[:userinfo].to_s
17
17
  raise Xlogin::GeneralError.new('Argument error.') unless @host && @port
18
18
 
19
19
  @prompts = @opts[:prompts] || [[/[$%#>] ?\z/n, nil]]
@@ -21,8 +21,6 @@ module Xlogin
21
21
 
22
22
  @loglist = [@opts[:log]].flatten.compact
23
23
  @logger = update_logger
24
-
25
- @mutex = Mutex.new
26
24
  end
27
25
 
28
26
  def waitfor(*expect)
@@ -39,26 +37,27 @@ module Xlogin
39
37
  end
40
38
  end
41
39
 
40
+ def dup(opts = @opts)
41
+ self.class.new(opts)
42
+ end
43
+
42
44
  def lock(timeout: @timeout)
43
- granted = false
45
+ @mutex ||= Mutex.new
44
46
 
45
47
  begin
46
48
  Timeout.timeout(timeout) { @mutex.lock }
47
- granted = true
48
49
  yield self
49
50
  ensure
50
- @mutex.unlock if @mutex.locked? && granted
51
+ @mutex.unlock if @mutex.locked?
51
52
  end
52
53
  end
53
54
 
54
55
  def with_retry(max_retry: 1)
55
- retry_count = 0
56
-
57
56
  begin
58
57
  yield self
59
58
  rescue => e
60
59
  renew if respond_to?(:renew)
61
- raise e if (retry_count += 1) > max_retry
60
+ raise e if (max_retry -= 1) < 0
62
61
  retry
63
62
  end
64
63
  end
data/lib/xlogin/ssh.rb CHANGED
@@ -8,7 +8,7 @@ module Xlogin
8
8
 
9
9
  def initialize(**opts)
10
10
  configure_session(opts.merge(port: opts[:port] || 22))
11
- username, password = @userinfo
11
+ username, password = @userinfo.split(':')
12
12
 
13
13
  super(
14
14
  'Host' => @host,
data/lib/xlogin/telnet.rb CHANGED
@@ -17,11 +17,7 @@ module Xlogin
17
17
  'Prompt' => Regexp.union(*@prompts.map(&:first))
18
18
  )
19
19
 
20
- login(*@userinfo) if respond_to?(:login) && !@userinfo.empty?
21
- end
22
-
23
- def renew(opts = @opts)
24
- self.class.new(opts).tap { |s| @sock = s.sock }
20
+ login(*@userinfo.split(':')) if respond_to?(:login) && !@userinfo.empty?
25
21
  end
26
22
 
27
23
  def interact!
@@ -1,3 +1,3 @@
1
1
  module Xlogin
2
- VERSION = "0.4.13"
2
+ VERSION = "0.4.14"
3
3
  end
data/lib/xlogin.rb CHANGED
@@ -8,14 +8,16 @@ module Xlogin
8
8
 
9
9
  class GeneralError < StandardError; end
10
10
 
11
- BUILDIN_TEMPLATES = Dir.glob(File.join(File.dirname(__FILE__), 'xlogin', 'templates', '*.rb'))
11
+ BUILTIN_TEMPLATES = Dir.glob(File.join(File.dirname(__FILE__), 'xlogin', 'templates', '*.rb'))
12
12
 
13
13
  class << self
14
14
  def factory
15
- @factory ||= load_templates(*BUILDIN_TEMPLATES)
15
+ @factory ||= load_templates
16
16
  end
17
17
 
18
18
  def load_templates(*template_files)
19
+ template_files += BUILTIN_TEMPLATES if template_files.empty?
20
+
19
21
  @loaded_template_files ||= []
20
22
  Xlogin::FirmwareFactory.instance.tap do |factory|
21
23
  files = template_files - @loaded_template_files
@@ -25,6 +27,12 @@ module Xlogin
25
27
  end
26
28
 
27
29
  def source(*source_files)
30
+ if source_files.empty?
31
+ source_dirs = [ENV['HOME'], Dir.pwd]
32
+ source_names = ['_xloginrc', '.xloginrc']
33
+ source_files += source_dirs.product(source_names).map { |d, n| File.join(d, n) }
34
+ end
35
+
28
36
  _factory = Xlogin::FirmwareFactory.instance
29
37
  _factory.source(*source_files)
30
38
  end
@@ -42,6 +50,7 @@ module Xlogin
42
50
  end
43
51
 
44
52
  def get(hostname, args = {})
53
+ source if factory.list.empty?
45
54
  session = factory.build_from_hostname(hostname, args)
46
55
 
47
56
  if block_given?
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.4.13
4
+ version: 0.4.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - haccht
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-25 00:00:00.000000000 Z
11
+ date: 2017-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-telnet
@@ -113,6 +113,7 @@ files:
113
113
  - bin/setup
114
114
  - bin/xlogin
115
115
  - lib/xlogin.rb
116
+ - lib/xlogin/cli.rb
116
117
  - lib/xlogin/delegator.rb
117
118
  - lib/xlogin/firmware.rb
118
119
  - lib/xlogin/firmware_factory.rb