xlogin 0.14.1 → 0.14.2
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/lib/xlogin.rb +1 -1
- data/lib/xlogin/cli.rb +27 -24
- data/lib/xlogin/factory.rb +12 -16
- data/lib/xlogin/rake_task.rb +18 -25
- data/lib/xlogin/session.rb +38 -45
- data/lib/xlogin/session_pool.rb +4 -4
- data/lib/xlogin/spec.rb +11 -18
- data/lib/xlogin/template.rb +14 -24
- data/lib/xlogin/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 547e74e0f0fa2ffc7c30a9d809e7459eea4776c7a902e7f30f1c2e109e7b9a6a
|
4
|
+
data.tar.gz: e810cb9efb8098ce1acd8063f7de24f63876676b03819a06a329a04e010c588c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17373511e6a0f038ca63e6c7721d45eb3e1f8ef2c8a0f02ae287a0eeb0af51bc59f302ae7aaf27ae2b0d8f6c99673426744c33a1cb052d13d3d6b63a81a130cf
|
7
|
+
data.tar.gz: f0258f43d91d1043c5cf55ead1e71aba4e25df7cee36c2f6f3e34b528f66c62702280bfa5802840ab985e3a03988b1f0c89da69cd50a09d27d02c2842a7eae68
|
data/lib/xlogin.rb
CHANGED
data/lib/xlogin/cli.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
|
3
1
|
require 'optparse'
|
4
2
|
require 'parallel'
|
5
3
|
require 'stringio'
|
@@ -7,21 +5,22 @@ require 'stringio'
|
|
7
5
|
module Xlogin
|
8
6
|
class CLI
|
9
7
|
|
10
|
-
|
11
|
-
|
8
|
+
DEFAULT_INVENTORY = File.join(ENV['HOME'], '.xloginrc')
|
9
|
+
DEFAULT_TEMPLATE = File.join(ENV['HOME'], '.xlogin.d')
|
12
10
|
|
13
11
|
def self.run(args = ARGV)
|
14
12
|
Xlogin::CLI.new.run(args)
|
15
13
|
end
|
16
14
|
|
17
15
|
def list(config)
|
18
|
-
puts Xlogin.list(*config[:
|
16
|
+
puts Xlogin.list(*config[:patterns]).map{ |e| e[:name] }.sort.uniq
|
19
17
|
end
|
20
18
|
|
21
19
|
def tty(config)
|
22
|
-
info = Xlogin.
|
20
|
+
info = Xlogin.find(*config[:patterns])
|
23
21
|
puts "Trying #{info[:name]}...", "Escape character is '^]'."
|
24
|
-
|
22
|
+
|
23
|
+
session, _ = exec(config.merge(patterns: info[:name], jobs: 1))
|
25
24
|
session.interact!
|
26
25
|
end
|
27
26
|
|
@@ -29,8 +28,9 @@ module Xlogin
|
|
29
28
|
Signal.trap(:INT){ exit 0 }
|
30
29
|
|
31
30
|
jobs = config[:jobs] || 1
|
32
|
-
hosts = Xlogin.list(*config[:
|
31
|
+
hosts = Xlogin.list(*config[:patterns])
|
33
32
|
width = hosts.map{ |e| e[:name].length }.max
|
33
|
+
raise "No host found: `#{config[:patterns].join(', ')}`" if hosts.empty?
|
34
34
|
|
35
35
|
Parallel.map(hosts, in_threads: jobs) do |info|
|
36
36
|
buffer = StringIO.new
|
@@ -40,12 +40,12 @@ module Xlogin
|
|
40
40
|
begin
|
41
41
|
loggers = []
|
42
42
|
loggers << ((jobs > 1)? buffer : $stdout)
|
43
|
-
loggers << File.expand_path(File.join(config[:
|
43
|
+
loggers << File.expand_path(File.join(config[:logdir], "#{info[:name]}.log"), ENV['PWD']) if config[:logdir]
|
44
44
|
|
45
45
|
session = Xlogin.get(info.merge(log: loggers))
|
46
46
|
session.enable(session.config.enable) if session.config.enable && Xlogin.settings.enable?
|
47
47
|
|
48
|
-
command_lines =
|
48
|
+
command_lines = config[:command].flat_map { |e| e.to_s.split(';').map(&:strip) }
|
49
49
|
command_lines.each{ |line| session.cmd(line) }
|
50
50
|
|
51
51
|
buffer.string.lines.each{ |line| print prefix + line.gsub("\r", '') } if jobs > 1
|
@@ -60,33 +60,36 @@ module Xlogin
|
|
60
60
|
|
61
61
|
def run(args)
|
62
62
|
config = Hash.new
|
63
|
-
config[:env] =
|
63
|
+
config[:env] = []
|
64
|
+
config[:inventory] = []
|
65
|
+
config[:template] = []
|
66
|
+
config[:command] = []
|
64
67
|
config[:runner] = self.method(:tty)
|
65
|
-
config[:inventory] = DEFAULT_INVENTORY_FILE
|
66
|
-
config[:template] = DEFAULT_TEMPLATE_DIR
|
67
68
|
|
68
69
|
parser = OptionParser.new
|
69
70
|
parser.banner = "#{File.basename($0)} HOST_PATTERN [Options]"
|
70
71
|
parser.version = Xlogin::VERSION
|
71
72
|
|
72
|
-
parser.on('-i PATH', '--inventory', String, 'The PATH to the inventory file.')
|
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.'){ |v| v
|
73
|
+
parser.on('-i PATH', '--inventory', String, 'The PATH to the inventory file.') { |v| config[:inventory] << v }
|
74
|
+
parser.on('-t PATH', '--template', String, 'The PATH to the template file or directory.'){ |v| config[:template] << v }
|
75
|
+
parser.on('-L PATH', '--log-dir', String, 'The PATH to the log directory.') { |v| config[:logdir] = v }
|
75
76
|
|
76
77
|
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
|
+
parser.on('-e COMMAND', '--exec', String, 'Execute commands and quit.'){ |v| config[:runner] = self.method(:exec); config[:command] << v }
|
78
79
|
|
79
|
-
parser.on('-E KEY=VAL', '--env', /(\w+=\w+)+/, 'Environment variables.')
|
80
|
-
parser.on('-j NUM', '--jobs', Integer, 'The NUM of jobs to execute in parallel.')
|
80
|
+
parser.on('-E KEY=VAL', '--env', /(\w+=\w+)+/, 'Environment variables.') { |v| config[:env] << v }
|
81
|
+
parser.on('-j NUM', '--jobs', Integer, 'The NUM of jobs to execute in parallel.'){ |v| config[:jobs] = v }
|
81
82
|
|
82
|
-
config[:
|
83
|
+
config[:patterns] = parser.parse!(args)
|
84
|
+
config[:inventory] << DEFAULT_INVENTORY if config[:inventory].empty?
|
85
|
+
config[:template] << DEFAULT_TEMPLATE if config[:template].empty?
|
83
86
|
|
84
87
|
Xlogin.configure do
|
85
|
-
set
|
86
|
-
|
87
|
-
|
88
|
+
set Hash[config[:env].map{ |v| v.split('=') }]
|
89
|
+
|
90
|
+
source *config[:inventory].map{ |e| File.expand_path(e, ENV['PWD']) }
|
91
|
+
template *config[:template].map { |e| File.expand_path(e, ENV['PWD']) }
|
88
92
|
end
|
89
|
-
raise "No host found: `#{args.join(', ')}`" if Xlogin.list(*config[:pattern]).empty?
|
90
93
|
|
91
94
|
config[:runner].call(config)
|
92
95
|
rescue => e
|
data/lib/xlogin/factory.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'addressable/uri'
|
2
|
+
require 'net/ssh/gateway'
|
2
3
|
require 'singleton'
|
3
4
|
require 'thread'
|
4
5
|
require 'xlogin/session_pool'
|
@@ -16,15 +17,16 @@ module Xlogin
|
|
16
17
|
@mutex = Mutex.new
|
17
18
|
end
|
18
19
|
|
19
|
-
def
|
20
|
-
@inventory[name] = (
|
20
|
+
def set_hostinfo(name, **opts)
|
21
|
+
@inventory[name] = (get_hostinfo(name) || {name: name}).merge(opts)
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
+
def get_hostinfo(name)
|
24
25
|
@inventory[name]
|
25
26
|
end
|
26
27
|
|
27
|
-
def
|
28
|
+
def list_hostinfo(*patterns)
|
29
|
+
return [] if patterns == [nil]
|
28
30
|
return @inventory.values if patterns.empty?
|
29
31
|
|
30
32
|
values1 = patterns.map do |pattern|
|
@@ -94,31 +96,25 @@ module Xlogin
|
|
94
96
|
end
|
95
97
|
|
96
98
|
def build_from_hostname(args, **opts)
|
97
|
-
hostinfo =
|
99
|
+
hostinfo = get_hostinfo(args)
|
98
100
|
raise Xlogin::Error.new("Host not found: '#{args}'") unless hostinfo
|
99
101
|
|
100
|
-
build(hostinfo.merge(
|
102
|
+
build(**hostinfo.merge(**opts))
|
101
103
|
end
|
102
104
|
|
103
105
|
def method_missing(method_name, *args, **opts, &block)
|
104
|
-
super unless args.size == 2 &&
|
106
|
+
super unless args.size == 2 && Addressable::URI::URIREGEX =~ args[1]
|
105
107
|
|
106
|
-
type = method_name.to_s.downcase
|
107
108
|
name = args[0]
|
108
109
|
uri = args[1]
|
109
|
-
|
110
|
+
type = method_name.to_s.downcase
|
111
|
+
set_hostinfo(name.to_s, type: type, uri: uri, **opts)
|
110
112
|
end
|
111
113
|
|
112
114
|
private
|
113
115
|
def uri(**opts)
|
114
116
|
return Addressable::URI.parse(opts[:uri].strip) if opts.key?(:uri)
|
115
|
-
|
116
|
-
scheme = opts[:scheme].strip
|
117
|
-
address = opts.values_at(:host, :port).compact.map(&:strip).join(':')
|
118
|
-
userinfo = opts[:userinfo].strip
|
119
|
-
userinfo ||= opts.values_at(:username, :password).compact.map(&:strip).join(':')
|
120
|
-
|
121
|
-
Addressable::URI.parse("#{scheme}://" + [userinfo, address].compact.join('@'))
|
117
|
+
Addressable::URI.new(**opts)
|
122
118
|
rescue
|
123
119
|
raise Xlogin::Error.new("Invalid target - '#{opts}'")
|
124
120
|
end
|
data/lib/xlogin/rake_task.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'time'
|
2
2
|
require 'rake'
|
3
3
|
require 'rake/tasklib'
|
4
|
-
require 'ostruct'
|
5
4
|
require 'stringio'
|
6
5
|
require 'colorize'
|
7
6
|
|
@@ -17,7 +16,7 @@ module Xlogin
|
|
17
16
|
|
18
17
|
task 'all' => hostnames unless opts[:all] == false
|
19
18
|
hostnames.each do |hostname|
|
20
|
-
desc "#{description}
|
19
|
+
desc "#{description} with #{hostname}"
|
21
20
|
RakeTask.new(hostname, &block)
|
22
21
|
end
|
23
22
|
end
|
@@ -32,8 +31,8 @@ module Xlogin
|
|
32
31
|
end
|
33
32
|
|
34
33
|
attr_reader :name
|
35
|
-
attr_accessor :lock
|
36
34
|
attr_accessor :log
|
35
|
+
attr_accessor :lock
|
37
36
|
attr_accessor :timeout
|
38
37
|
attr_accessor :silent
|
39
38
|
attr_accessor :fail_on_error
|
@@ -49,8 +48,8 @@ module Xlogin
|
|
49
48
|
define
|
50
49
|
end
|
51
50
|
|
52
|
-
def name_with_scope
|
53
|
-
[*Rake.application.current_scope.to_a.reverse, name].join(
|
51
|
+
def name_with_scope(separator = ':')
|
52
|
+
[*Rake.application.current_scope.to_a.reverse, name].join(separator)
|
54
53
|
end
|
55
54
|
|
56
55
|
def run(&block)
|
@@ -78,47 +77,41 @@ module Xlogin
|
|
78
77
|
end
|
79
78
|
|
80
79
|
def run_task
|
81
|
-
buffer
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
buffer = StringIO.new
|
81
|
+
loggers = []
|
82
|
+
loggers << log if log
|
83
|
+
loggers << $stdout if !silent && !Rake.application.options.always_multitask
|
84
|
+
loggers << buffer
|
86
85
|
|
87
|
-
session = Xlogin.get(name, log:
|
86
|
+
session = Xlogin.get(name, log: loggers, timeout: timeout)
|
88
87
|
|
89
88
|
@runner.call(session)
|
90
|
-
$stdout.print
|
89
|
+
$stdout.print log_text(buffer.string) if !silent && Rake.application.options.always_multitask
|
91
90
|
|
92
91
|
return true
|
93
92
|
rescue => e
|
94
93
|
RakeTask.shutdown! if fail_on_error
|
95
94
|
|
96
|
-
|
97
|
-
$stderr.print "\n"
|
98
|
-
$stderr.print "\n"
|
95
|
+
session.comment(e.to_s, prefix: "[ERROR]", chomp: true, color: :white, background: :red)
|
96
|
+
$stderr.print log_text(buffer.string + "\n").colorize(color: :light_red) if Rake.application.options.always_multitask
|
99
97
|
|
100
98
|
return false
|
101
99
|
ensure
|
102
100
|
session.close rescue nil
|
103
101
|
end
|
104
102
|
|
105
|
-
def
|
106
|
-
text.lines.map
|
107
|
-
"#{Time.now.iso8601} - #{name}\t|#{line.gsub(/^\s*[\r]+/, '')}"
|
108
|
-
end.join
|
103
|
+
def log_text(text)
|
104
|
+
text.lines.map{ |line| "#{Time.now.iso8601} - #{name}\t|#{line.gsub(/^\s*[\r]+/, '')}" }.join
|
109
105
|
end
|
110
106
|
|
111
107
|
end
|
112
108
|
|
113
109
|
module SessionModule
|
114
|
-
def log_message(text, prefix: "[INFO]", chomp: false, **color)
|
115
|
-
default_color = { color: :green }
|
116
110
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
log("#{prefix} #{text}".colorize(**default_color.merge(color)))
|
111
|
+
def comment(line, prefix: "[INFO]", chomp: false, **color)
|
112
|
+
write_log("#{prefix} #{line}".colorize(**color))
|
121
113
|
cmd('') unless chomp
|
122
114
|
end
|
115
|
+
|
123
116
|
end
|
124
117
|
end
|
data/lib/xlogin/session.rb
CHANGED
@@ -1,8 +1,4 @@
|
|
1
|
-
require 'addressable/uri'
|
2
|
-
require 'delegate'
|
3
1
|
require 'fileutils'
|
4
|
-
require 'net/ssh/gateway'
|
5
|
-
require 'ostruct'
|
6
2
|
require 'stringio'
|
7
3
|
require 'thread'
|
8
4
|
|
@@ -25,13 +21,11 @@ module Xlogin
|
|
25
21
|
@tunnel = opts[:tunnel] || opts[:via]
|
26
22
|
@config = ReadOnlyStruct.new(opts)
|
27
23
|
@template = template
|
28
|
-
@
|
29
|
-
|
30
|
-
max_retry = @config.retry || 1
|
24
|
+
@loggers = [@config.log].flatten.uniq.reduce({}){ |a, e| a.merge(e => build_log(e)) }
|
31
25
|
@host, @port = Xlogin.factory.open_tunnel(@tunnel, @host, @port) if @tunnel
|
32
26
|
|
33
|
-
|
34
|
-
|
27
|
+
max_retry = @config.retry || 1
|
28
|
+
username, password = uri.userinfo.to_s.split(':')
|
35
29
|
|
36
30
|
begin
|
37
31
|
args = Hash.new
|
@@ -43,8 +37,8 @@ module Xlogin
|
|
43
37
|
else
|
44
38
|
args['Host' ] = @host
|
45
39
|
args['Port' ] = @port
|
46
|
-
args['Username'] =
|
47
|
-
args['Password'] =
|
40
|
+
args['Username'] = username
|
41
|
+
args['Password'] = password
|
48
42
|
end
|
49
43
|
|
50
44
|
super(args)
|
@@ -64,43 +58,54 @@ module Xlogin
|
|
64
58
|
end
|
65
59
|
|
66
60
|
def prompt_pattern
|
67
|
-
Regexp.union(*@template.
|
61
|
+
Regexp.union(*@template.prompts.map(&:first))
|
68
62
|
end
|
69
63
|
|
70
64
|
def duplicate(type: @template.name, **args)
|
71
65
|
template = Xlogin::Factory.instance.get_template(type)
|
66
|
+
raise Xlogin::Error.new("Template not found: '#{type}'") unless template
|
67
|
+
|
72
68
|
template.build(@uri, **@config.to_h.merge(args))
|
73
69
|
end
|
74
70
|
|
75
|
-
def puts(
|
76
|
-
|
77
|
-
args.empty? ? super('', &block) : super(*args, &block)
|
71
|
+
def puts(string = '', &block)
|
72
|
+
super(string, &block)
|
78
73
|
end
|
79
74
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
75
|
+
def print(string = '', &block)
|
76
|
+
string = instance_exec(string, &@template.interrupt!) if @template.interrupt!
|
77
|
+
super(string, &block)
|
83
78
|
end
|
84
79
|
|
85
|
-
def
|
86
|
-
|
87
|
-
@mutex.synchronize do
|
88
|
-
@loggers.each do |_, logger|
|
89
|
-
next if logger.nil? || [$stdout, $stderr].include?(logger)
|
90
|
-
logger.close
|
91
|
-
end
|
80
|
+
def waitfor(*args, &block)
|
81
|
+
return waitfor(prompt_pattern) if args.empty?
|
92
82
|
|
93
|
-
|
94
|
-
|
83
|
+
line = super(*args) do |recv|
|
84
|
+
write_log(recv)
|
85
|
+
block.call(recv) if block
|
95
86
|
end
|
87
|
+
|
88
|
+
_, process = @template.prompts.find{ |r, p| r =~ line && p }
|
89
|
+
if process
|
90
|
+
instance_eval(&process)
|
91
|
+
line += waitfor(*args, &block)
|
92
|
+
end
|
93
|
+
|
94
|
+
return line
|
96
95
|
end
|
97
96
|
|
98
|
-
def
|
99
|
-
@loggers.each
|
97
|
+
def close
|
98
|
+
@loggers.each do |_, logger|
|
99
|
+
next if [$stdout, $stderr, nil].include?(logger)
|
100
|
+
logger.close
|
101
|
+
end
|
102
|
+
|
103
|
+
Xlogin.factory.close_tunnel(@tunnel, @port) if @tunnel
|
104
|
+
super
|
100
105
|
end
|
101
106
|
|
102
107
|
def enable_log(log = $stdout)
|
103
|
-
@loggers.update(log =>
|
108
|
+
@loggers.update(log => build_log(log))
|
104
109
|
if block_given?
|
105
110
|
yield
|
106
111
|
disable_log(log)
|
@@ -116,23 +121,11 @@ module Xlogin
|
|
116
121
|
end
|
117
122
|
|
118
123
|
private
|
119
|
-
def
|
120
|
-
|
121
|
-
line = __waitfor.call(*args) do |recv|
|
122
|
-
log(recv)
|
123
|
-
block.call(recv) if block
|
124
|
-
end
|
125
|
-
|
126
|
-
_, process = @template.prompt.find{ |r, p| r =~ line && p }
|
127
|
-
if process
|
128
|
-
instance_eval(&process)
|
129
|
-
line += _waitfor(*args, &block)
|
130
|
-
end
|
131
|
-
|
132
|
-
return line
|
124
|
+
def write_log(text)
|
125
|
+
@loggers.each{ |_, logger| logger.syswrite(text) if logger }
|
133
126
|
end
|
134
127
|
|
135
|
-
def
|
128
|
+
def build_log(log)
|
136
129
|
case log
|
137
130
|
when String
|
138
131
|
FileUtils.mkdir_p(File.dirname(log))
|
data/lib/xlogin/session_pool.rb
CHANGED
@@ -37,8 +37,8 @@ module Xlogin
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def close
|
40
|
-
|
41
|
-
session, _
|
40
|
+
until @queue.empty?
|
41
|
+
session, _ = @queue.deq
|
42
42
|
destroy(session)
|
43
43
|
end
|
44
44
|
end
|
@@ -58,10 +58,10 @@ module Xlogin
|
|
58
58
|
end
|
59
59
|
|
60
60
|
begin
|
61
|
-
raise IOError if session
|
61
|
+
raise IOError if session&.sock&.closed?
|
62
62
|
rescue IOError, EOFError, Errno::ECONNABORTED, Errno::ECONNREFUSED, Errno::ECONNRESET
|
63
63
|
destroy(session)
|
64
|
-
|
64
|
+
return deq
|
65
65
|
end
|
66
66
|
|
67
67
|
session
|
data/lib/xlogin/spec.rb
CHANGED
@@ -2,7 +2,7 @@ module Xlogin
|
|
2
2
|
class ExpectationError < StandardError
|
3
3
|
|
4
4
|
def initialize(expect, actual)
|
5
|
-
super(
|
5
|
+
super(expect)
|
6
6
|
@actual = actual
|
7
7
|
end
|
8
8
|
|
@@ -14,28 +14,22 @@ module Xlogin
|
|
14
14
|
|
15
15
|
class Expectation
|
16
16
|
|
17
|
-
def initialize(
|
18
|
-
@
|
19
|
-
@args = args
|
17
|
+
def initialize(result)
|
18
|
+
@result = result
|
20
19
|
end
|
21
20
|
|
22
21
|
def to_match(regexp)
|
23
|
-
|
24
|
-
|
25
|
-
end
|
22
|
+
regexp = Regexp.new(regexp.to_s) unless regexp.kind_of?(Regexp)
|
23
|
+
return if @result =~ regexp
|
26
24
|
|
27
|
-
|
28
|
-
return unless match(regexp)
|
29
|
-
raise ExpectationError.new(@expect, @actual)
|
25
|
+
raise ExpectationError.new("Expected to match #{regexp}", @result)
|
30
26
|
end
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
@expect = regexp.inspect
|
28
|
+
def not_to_match(regexp)
|
29
|
+
regexp = Regexp.new(regexp.to_s) unless regexp.kind_of?(Regexp)
|
30
|
+
return if @result !~ regexp
|
36
31
|
|
37
|
-
|
38
|
-
@actual =~ regexp
|
32
|
+
raise ExpectationError.new("Expected not to match #{regexp}", @result)
|
39
33
|
end
|
40
34
|
|
41
35
|
end
|
@@ -43,9 +37,8 @@ module Xlogin
|
|
43
37
|
module SessionModule
|
44
38
|
|
45
39
|
def expect(*args)
|
46
|
-
Expectation.new(
|
40
|
+
Expectation.new(cmd(*args))
|
47
41
|
end
|
48
|
-
alias_method :exp, :expect
|
49
42
|
|
50
43
|
end
|
51
44
|
end
|
data/lib/xlogin/template.rb
CHANGED
@@ -8,54 +8,44 @@ module Xlogin
|
|
8
8
|
DEFAULT_PROMPT = /[$%#>] ?\z/n
|
9
9
|
RESERVED_METHODS = %i( login logout enable disable )
|
10
10
|
|
11
|
-
attr_reader :name, :
|
11
|
+
attr_reader :name, :methods
|
12
12
|
|
13
13
|
def initialize(name)
|
14
14
|
@name = name
|
15
|
-
@scopes = Hash.new
|
16
|
-
@timeout = DEFAULT_TIMEOUT
|
17
15
|
@prompts = Array.new
|
18
16
|
@methods = Hash.new
|
17
|
+
@timeout = DEFAULT_TIMEOUT
|
19
18
|
@interrupt = nil
|
20
19
|
end
|
21
20
|
|
22
|
-
def
|
23
|
-
@
|
24
|
-
@timeout
|
21
|
+
def prompt(expect, &block)
|
22
|
+
@prompts << [Regexp.new(expect.to_s), block]
|
25
23
|
end
|
26
24
|
|
27
|
-
def
|
28
|
-
|
29
|
-
@prompts << [Regexp.new(expect.to_s), block] if expect
|
25
|
+
def prompts
|
26
|
+
@prompts << [DEFAULT_PROMPT, nil] if @prompts.empty?
|
30
27
|
@prompts
|
31
28
|
end
|
32
29
|
|
33
|
-
def
|
34
|
-
@
|
30
|
+
def bind(name, &block)
|
31
|
+
@methods[name] = block
|
35
32
|
end
|
36
33
|
|
37
|
-
def
|
38
|
-
@
|
34
|
+
def timeout(val = nil)
|
35
|
+
@timeout = val.to_i if val
|
36
|
+
@timeout
|
39
37
|
end
|
40
38
|
|
41
39
|
def interrupt!(&block)
|
42
|
-
|
43
|
-
@interrupt
|
40
|
+
@interrupt = block if block
|
41
|
+
@interrupt
|
44
42
|
end
|
45
43
|
|
46
44
|
def build(uri, **opts)
|
47
45
|
klass = Class.new(Xlogin.const_get(uri.scheme.capitalize))
|
48
46
|
klass.class_exec(self) do |template|
|
49
|
-
scopes = [*opts[:scope]].compact
|
50
|
-
scopes.each{ |scope| template.instance_eval(&template.scopes[scope]) }
|
51
|
-
|
52
47
|
template.methods.each do |name, block|
|
53
|
-
|
54
|
-
when 'enable'
|
55
|
-
define_method(name){ |args = nil| instance_exec(args || opts[:enable], &block) }
|
56
|
-
else
|
57
|
-
define_method(name, &block)
|
58
|
-
end
|
48
|
+
define_method(name, &block)
|
59
49
|
end
|
60
50
|
end
|
61
51
|
|
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.14.
|
4
|
+
version: 0.14.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- haccht
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-telnet
|