xlogin 0.3.7 → 0.4.1

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: 4ea3547deaca69452375126dadf928ae75336be3
4
- data.tar.gz: 8dc72eb01028ca3f85ba0a5eb7b7eb959f47388c
3
+ metadata.gz: 01f1dcfc4664204170ef0065396788768d5ac676
4
+ data.tar.gz: a4bf5740a6ca77b67a64497b7cded0942e689f9e
5
5
  SHA512:
6
- metadata.gz: 858d6eb742ed5f93c43f2b886039f00ba136abf10f3d5ac06dce59a881338fccbae0a8b9371f1cfa5220c1cad6c5baeaa0dd7a9baab880e2379e13dbeeb02f46
7
- data.tar.gz: 65e11182a15cec1c91f8f9181d239ba348acbfe54735cb12991f67385e7cb35d625feacf729650451a9e3e0719d8f81658ad386bd9f781fd6a929c06224adcb6
6
+ metadata.gz: e8bf704c7af2aef3f090951d94088d8ec49c985eff1226333be5d540a0171e1022efdb7cad142c5642d11024418c91d0e695f7c01d0dac4f388454433f550706
7
+ data.tar.gz: fc21595ec2a4acb907eb9f6dfd77154f3097b8afff7e7e21fd1548e8ca14d617e183a0bd7f56de3238006975f588f2f3a43ca2c4d62216c71c0d513ac233be68
data/.gitignore CHANGED
@@ -56,5 +56,9 @@ build-iPhoneSimulator/
56
56
  # End of https://www.gitignore.io/api/ruby
57
57
  /lib/xlogin/.xloginrc
58
58
  /lib/xlogin/_xloginrc
59
- /lib/xlogin/firmware_templates/*
60
- !/lib/xlogin/firmware_templates/vyos.rb
59
+ /lib/xlogin/templates/*
60
+ !/lib/xlogin/templates/vyos.rb
61
+ !/lib/xlogin/templates/junos.rb
62
+ !/lib/xlogin/templates/ios.rb
63
+ !/lib/xlogin/templates/iosxr.rb
64
+ !/lib/xlogin/templates/sros.rb
data/bin/cmd_exec CHANGED
@@ -46,7 +46,6 @@ module Xlogin
46
46
  opt.on('-H', 'Display hostnames for each response.') { |v| options[:H] = v }
47
47
 
48
48
  opt.on('-f FILE', 'Read target hostnames from FILE.') { |v| options[:f] = v }
49
- opt.on('-r FILE', 'Load extention library.') { |v| options[:r] = v }
50
49
 
51
50
  opt.on('-x VALUE', 'Read commands from VALUE.') { |v| options[:x] = v }
52
51
  opt.on('-c VALUE') { |v| options[:c] = v }
@@ -74,9 +73,9 @@ module Xlogin
74
73
  usage if options[:x].nil? and options[:c].nil?
75
74
  usage if options[:f].nil? && args.empty?
76
75
 
77
- if options[:r]
78
- options[:r].split(':').each { |file| require file }
79
- end
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)
80
79
 
81
80
  size = (options[:p] || 1).to_i
82
81
  interval = (options[:i] || 0).to_i
data/bin/xlogin CHANGED
@@ -12,7 +12,6 @@ module Xlogin
12
12
  opt = OptionParser.new
13
13
  opt.on('-e', '--enable', 'Try to gain enable priviledge.') { |v| options[:e] = v }
14
14
  opt.on('-l', '--log', 'Enable logging.') { |v| options[:l] = v }
15
- opt.on('-r FILE', 'Load extention library.') { |v| options[:r] = v }
16
15
 
17
16
  opt.on( '--list', 'List all devices.') { |v| options[:list] = v }
18
17
 
@@ -34,9 +33,9 @@ module Xlogin
34
33
  def self.run(args = ARGV)
35
34
  options, args = getopts(args)
36
35
 
37
- if options[:r]
38
- options[:r].split(':').each { |file| require file }
39
- end
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)
40
39
 
41
40
  if options[:list]
42
41
  puts Xlogin.factory.list.map { |e| "#{e[:name]}\t#{e[:type]}" }
data/lib/xlogin.rb CHANGED
@@ -8,29 +8,24 @@ module Xlogin
8
8
 
9
9
  class GeneralError < StandardError; end
10
10
 
11
+ # default template directory
12
+ TEMPLATE_DIR = File.join(File.dirname(__FILE__), 'xlogin', 'templates')
13
+
11
14
  class << self
12
15
  def factory
16
+ @factory ||= configure_factory
17
+ end
18
+
19
+ def configure_factory(*template_dirs)
13
20
  unless @factory
14
21
  @factory = Xlogin::FirmwareFactory.instance
15
22
 
16
- template_dir = File.join(File.dirname(__FILE__), 'xlogin', 'firmware_templates')
17
-
18
- Dir.entries(template_dir).each do |file|
19
- @factory.load_template_file(File.join(template_dir, file))
20
- end
21
-
22
- source_dirs = [
23
- ENV['HOME'],
24
- ENV['XLOGIN_HOME'],
25
- Dir.pwd
26
- ]
27
-
28
- source_dirs.compact.uniq.each do |dir|
29
- @factory.source(File.join(dir, '.xloginrc'))
30
- @factory.source(File.join(dir, '_xloginrc'))
23
+ template_dirs = [TEMPLATE_DIR, File.join(Dir.pwd, 'templates'), *template_dirs]
24
+ template_dirs.compact.uniq.each do |dir|
25
+ next unless FileTest.directory?(dir)
26
+ @factory.load_template_file(*Dir.glob(File.join(dir, '*.rb')))
31
27
  end
32
28
  end
33
-
34
29
  @factory
35
30
  end
36
31
 
@@ -41,11 +36,8 @@ module Xlogin
41
36
  factory.set_template(name, template)
42
37
  end
43
38
 
44
- def alias(new_name, original_name)
45
- template = factory.get_template(original_name)
46
- raise Xlogin::GeneralError.new("'#{original_name}' not found") unless template
47
-
48
- factory.set_template(new_name, template)
39
+ def alias(new_name, name)
40
+ factory.alias_template(new_name, name)
49
41
  end
50
42
 
51
43
  def get(hostname, args = {})
@@ -59,8 +51,4 @@ module Xlogin
59
51
  end
60
52
  end
61
53
 
62
- # do not remove this line!
63
- # initialize Xlogin systems and load related modules beforehand.
64
- Xlogin.factory
65
-
66
54
  end
@@ -11,13 +11,17 @@ module Xlogin
11
11
  def initialize
12
12
  @database = Hash.new
13
13
  @templates = Hash.new
14
+ @aliases = Hash.new
14
15
  end
15
16
 
16
- def load_template_file(file)
17
- require file if file =~ /.rb$/
17
+ def load_template_file(*files)
18
+ files.each do |file|
19
+ require file if file =~ /.rb$/
20
+ end
18
21
  end
19
22
 
20
23
  def get_template(name)
24
+ name = @aliases[name] || name
21
25
  @templates[name.to_s.downcase]
22
26
  end
23
27
 
@@ -29,11 +33,15 @@ module Xlogin
29
33
  @templates.keys
30
34
  end
31
35
 
32
- def source(db_file)
33
- return unless File.exist?(db_file)
36
+ def alias_template(new_name, name)
37
+ @aliases[new_name.to_s.downcase] = name
38
+ end
34
39
 
35
- content = IO.read(db_file)
36
- instance_eval(content)
40
+ def source(*files)
41
+ files.compact.uniq.each do |file|
42
+ next unless File.exist?(file)
43
+ instance_eval(IO.read(file))
44
+ end
37
45
  end
38
46
 
39
47
  def get(name)
@@ -55,7 +63,10 @@ module Xlogin
55
63
  opts = args.reduce({}) { |a, (k, v)| a.merge(k.to_s.downcase.to_sym => v) }
56
64
  raise Xlogin::GeneralError.new("Host not found: #{args}") unless uri && type
57
65
 
58
- session = get_template(type).dup.run(uri, opts)
66
+ template = get_template(type)
67
+ raise Xlogin::GeneralError.new("Template not defined: #{type}") unless template
68
+
69
+ session = template.dup.run(uri, opts)
59
70
  session.name = name if name
60
71
  session
61
72
  end
@@ -68,7 +79,7 @@ module Xlogin
68
79
  end
69
80
 
70
81
  def method_missing(name, *args, &block)
71
- super unless caller_locations.first.label == "source"
82
+ super unless caller_locations.first.label =~ /source/ and args.size >= 2
72
83
 
73
84
  type = name.to_s.downcase
74
85
  name = args.shift
@@ -9,9 +9,18 @@ module Xlogin
9
9
  class << self
10
10
  include Rake::DSL
11
11
 
12
- def bulk(names, **xlogin_opts, &block)
13
- names = names.map(&:strip).grep(/^\s*[^#]/)
12
+ def mutex
13
+ @mutex ||= Mutex.new
14
+ end
15
+
16
+ def source(file, &block)
17
+ Xlogin.factory.source(file)
18
+ hostnames = Xlogin.factory.list.map { |e| e[:name] }
19
+ bulk(hostnames, &block)
20
+ end
14
21
 
22
+ def bulk(names, &block)
23
+ names = names.map(&:strip).grep(/^\s*[^#]/)
15
24
  namecount = names.uniq.inject({}) { |a, e| a.merge(e => names.count(e)) }
16
25
  duplicate = namecount.keys.select { |name| namecount[name] > 1 }
17
26
  raise Xlogin::GeneralError.new("Duplicate hosts found - #{duplicate.join(', ')}") unless duplicate.empty?
@@ -21,15 +30,11 @@ module Xlogin
21
30
 
22
31
  names.each do |name|
23
32
  desc "#{description} (#{name})"
24
- RakeTask.new(name, **xlogin_opts, &block)
33
+ RakeTask.new(name, &block)
25
34
  end
26
35
  end
27
36
  end
28
37
 
29
- def mutex
30
- @mutex ||= Mutex.new
31
- end
32
-
33
38
  def current_namespace
34
39
  path = Rake.application.current_scope.path
35
40
 
@@ -46,23 +51,24 @@ module Xlogin
46
51
 
47
52
 
48
53
  attr_reader :name
54
+ attr_accessor :xlogin_opts
49
55
  attr_accessor :fail_on_error
50
56
  attr_accessor :silent
51
57
  attr_accessor :lockfile
52
58
  attr_accessor :logfile
53
59
  attr_accessor :uncomment
54
60
 
55
- def initialize(name, **xlogin_opts)
61
+ def initialize(name)
56
62
  @name = name
63
+ @xlogin_opts = Xlogin.factory.get(name) || {}
64
+ @session = nil
65
+ @taskrunner = nil
66
+
57
67
  @fail_on_error = true
58
68
  @silent = Rake.application.options.silent
59
69
  @lockfile = nil
60
70
  @logfile = nil
61
71
  @uncomment = false
62
- @xlogin_opts = xlogin_opts
63
-
64
- @session = nil
65
- @taskrunner = nil
66
72
 
67
73
  yield(self) if block_given?
68
74
  define
@@ -86,9 +92,7 @@ module Xlogin
86
92
  private
87
93
  def define
88
94
  RakeTask.current_namespace do
89
- description = Rake.application.last_description || "Run '#{RakeTask.current_namespace}'"
90
-
91
- desc description
95
+ desc Rake.application.last_description || "Run '#{RakeTask.current_namespace}'"
92
96
  Rake.application.last_description = nil if uncomment
93
97
 
94
98
  if lockfile
@@ -108,24 +112,29 @@ module Xlogin
108
112
  end
109
113
 
110
114
  def run_task
111
- loggers = []
115
+ raise Xlogin::GeneralError.new("missing xlogin_opts to connect to #{name}") unless @xlogin_opts[:type] && @xlogin_opts[:uri]
116
+
117
+ loggers = [@xlogin_opts[:log]].flatten.compact
112
118
  loggers << $stdout unless silent || Rake.application.options.always_multitask
113
119
 
114
120
  if logfile
115
121
  mkdir_p(File.dirname(logfile), verbose: Rake.application.options.trace)
116
- loggers << logfile if logfile
122
+ loggers << logfile
117
123
  end
118
124
 
119
125
  @xlogin_opts[:log] = loggers unless loggers.empty?
120
126
 
121
127
  begin
122
- @session = Xlogin.get(name, @xlogin_opts.dup)
123
- @session.extend(SessionExt)
128
+ @session = Xlogin.factory.build(@xlogin_opts)
129
+ if @session && @taskrunner
130
+ @session.extend(SessionExt)
124
131
 
125
- method_proc = method(:safe_puts)
126
- @session.define_singleton_method(:safe_puts) { |*args| method_proc.call(*args) }
132
+ # pass RakeTask#safe_puts method to the session instance.
133
+ method_proc = method(:safe_puts)
134
+ @session.define_singleton_method(:safe_puts) { |*args| method_proc.call(*args) }
127
135
 
128
- @taskrunner.call(@session) if @taskrunner && @session
136
+ @taskrunner.call(@session) if @taskrunner && @session
137
+ end
129
138
  rescue => e
130
139
  raise e if fail_on_error
131
140
  safe_puts(e, io: $stderr, force: true)
@@ -160,14 +169,9 @@ module Xlogin
160
169
  cmd(my_command)
161
170
  else
162
171
  cmd(my_command)
163
- # retry thid command
164
172
  readline(command)
165
173
  end
166
174
  end
167
-
168
- def sync(&block)
169
- RakeTask.mutex.synchronize(&block) if block
170
- end
171
175
  end
172
176
 
173
177
  end
@@ -20,6 +20,25 @@ module Xlogin
20
20
  @logger = update_logger
21
21
  end
22
22
 
23
+ def thread_safe(timeout: @timeout, maximum_retry: 1)
24
+ @safe_session = self
25
+ @safe_session_mutex ||= Mutex.new
26
+
27
+ Timeout.timeout(timeout) do
28
+ @safe_session_mutex.synchronize do
29
+ retry_count = 0
30
+ begin
31
+ @safe_session ||= Xlogin.get(@host, @opts)
32
+ yield @safe_session
33
+ rescue Errno::ECONNRESET => e
34
+ raise e unless (retry_count += 1) < maximum_retry
35
+ @safe_session = nil
36
+ retry
37
+ end
38
+ end
39
+ end
40
+ end
41
+
23
42
  def enable_log(out = $stdout)
24
43
  enabled = @loglist.include?(out)
25
44
  unless enabled
@@ -0,0 +1,36 @@
1
+ Xlogin.configure :ios do |os|
2
+ os.timeout(300)
3
+ os.prompt(/[>$#]/)
4
+ os.prompt(/yes \/ no: /) do
5
+ puts opts[:force] ? 'y' : 'n'
6
+ end
7
+
8
+ os.bind(:login) do |password|
9
+ waitfor(/Password: /) && puts(password)
10
+ waitfor
11
+ end
12
+
13
+ os.bind(:enable) do |password|
14
+ puts('enable')
15
+ waitfor(/Password: /) && puts(password)
16
+ waitfor
17
+ end
18
+
19
+ os.bind(:config) do
20
+ begin
21
+ cmd('terminal length 0')
22
+ resp = cmd('show run')
23
+ resp.lines[4..-2].join.to_s
24
+ ensure
25
+ cmd('exit')
26
+ end
27
+ end
28
+
29
+ os.bind(:save) do
30
+ begin
31
+ cmd('write memory')
32
+ ensure
33
+ cmd('exit')
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,22 @@
1
+ Xlogin.configure :iosxr do |os|
2
+ os.timeout(300)
3
+ os.prompt(/#\z/)
4
+
5
+ os.bind(:login) do |*args|
6
+ username, password = *args
7
+ waitfor(/Username: /) && puts(username)
8
+ waitfor(/Password: /) && puts(password)
9
+ waitfor
10
+ end
11
+
12
+ os.bind(:config) do
13
+ begin
14
+ cmd('terminal width 0')
15
+ cmd('terminal length 0')
16
+ resp = cmd('show run')
17
+ resp.lines[3..-3].join.to_s
18
+ ensure
19
+ cmd('exit')
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ Xlogin.configure :junos do |os|
2
+ os.timeout(300)
3
+ os.prompt(/[>#] \z/)
4
+
5
+ os.bind(:login) do |*args|
6
+ username, password = *args
7
+ waitfor(/login:\s/) && puts(username)
8
+ waitfor(/Password:/) && puts(password)
9
+ waitfor
10
+ end
11
+
12
+ os.bind(:config) do
13
+ begin
14
+ cmd('show configuration | no-more')
15
+ ensure
16
+ cmd('exit')
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ Xlogin.configure :sros do |os|
2
+ os.timeout(300)
3
+ os.prompt(/[>$#] /)
4
+ os.prompt(/y\/n:/) do
5
+ puts opts[:force] ? 'y' : 'n'
6
+ end
7
+
8
+ os.bind(:login) do |*args|
9
+ username, password = *args
10
+ waitfor(/Login:\s?/) && puts(username)
11
+ waitfor(/Password:\s?/) && puts(password)
12
+ waitfor
13
+ end
14
+
15
+ os.bind(:enable_admin) do |password|
16
+ puts('enable-admin')
17
+ waitfor(/Password:\s?/) && puts(password)
18
+ waitfor
19
+ end
20
+
21
+ os.bind(:config) do
22
+ begin
23
+ cmd('environment no more')
24
+ resp = cmd('admin display-config')
25
+ resp.lines[2..-2].join.to_s
26
+ ensure
27
+ cmd('logout')
28
+ end
29
+ end
30
+ end
@@ -24,5 +24,3 @@ Xlogin.configure :vyos do |os|
24
24
  end
25
25
  end
26
26
  end
27
-
28
- Xlogin.alias :edgeos, :vyos
@@ -1,3 +1,3 @@
1
1
  module Xlogin
2
- VERSION = "0.3.7"
2
+ VERSION = "0.4.1"
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.3.7
4
+ version: 0.4.1
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-11 00:00:00.000000000 Z
11
+ date: 2017-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -73,17 +73,16 @@ files:
73
73
  - lib/xlogin/delegator.rb
74
74
  - lib/xlogin/firmware.rb
75
75
  - lib/xlogin/firmware_factory.rb
76
- - lib/xlogin/firmware_templates/vyos.rb
77
76
  - lib/xlogin/gateway.rb
78
77
  - lib/xlogin/rake_task.rb
79
- - lib/xlogin/rspec.rb
80
- - lib/xlogin/rspec/context.rb
81
- - lib/xlogin/rspec/resource.rb
82
- - lib/xlogin/scanner.rb
83
78
  - lib/xlogin/session.rb
84
79
  - lib/xlogin/ssh.rb
85
80
  - lib/xlogin/telnet.rb
86
- - lib/xlogin/thread_safe.rb
81
+ - lib/xlogin/templates/ios.rb
82
+ - lib/xlogin/templates/iosxr.rb
83
+ - lib/xlogin/templates/junos.rb
84
+ - lib/xlogin/templates/sros.rb
85
+ - lib/xlogin/templates/vyos.rb
87
86
  - lib/xlogin/version.rb
88
87
  - xlogin.gemspec
89
88
  homepage: https://github.com/haccht/xlogin
data/lib/xlogin/rspec.rb DELETED
@@ -1,80 +0,0 @@
1
- require 'rspec'
2
- require 'stringio'
3
-
4
- require 'xlogin/rspec/context'
5
- require 'xlogin/rspec/resource'
6
-
7
- module Xlogin
8
-
9
- module RSpecResourceHelper
10
- def node(name)
11
- Resources::NodeResource.new(name)
12
- end
13
-
14
- def command(str)
15
- Resources::CommandResource.new(str)
16
- end
17
-
18
- def backend
19
- unless @backend
20
- context = Xlogin::Contexts.from_example(self)
21
- @backend = context.session if context && context.respond_to?(:session)
22
- end
23
- @backend
24
- end
25
- end
26
-
27
- module RSpecHelper
28
- def current_context
29
- @context
30
- end
31
-
32
- def method_missing(name, *args, &block)
33
- if current_context.respond_to?(name)
34
- current_context.send(name, *args, &block)
35
- else
36
- super(name, *args, &block)
37
- end
38
- end
39
- end
40
-
41
- end
42
-
43
-
44
- include Xlogin::RSpecResourceHelper
45
- module RSpec
46
- Matchers.define :match do |expected|
47
- match do |actual|
48
- response = actual.to_s.lines.slice(1..-1).join
49
- expected =~ response
50
- end
51
-
52
- failure_message do |actual|
53
- message = StringIO.new
54
- message.puts "Expect response to match #{expected.inspect}"
55
- message.puts "Result:"
56
- message.puts actual.to_s.lines.slice(1..-2).map { |line| " +#{line}" }
57
- message.string
58
- end
59
-
60
- failure_message_when_negated do |actual|
61
- message = StringIO.new
62
- message.puts "Expect response not to match #{expected.inspect}"
63
- message.puts "Result:"
64
- message.puts actual.to_s.lines.slice(1..-2).map { |line| " +#{line}" }
65
- message.string
66
- end
67
- end
68
-
69
- configure do |config|
70
- config.include Xlogin::RSpecHelper
71
-
72
- config.before(:all) do
73
- @context = Xlogin::Contexts.from_example(self.class)
74
- end
75
-
76
- config.before(:each) do
77
- @context = Xlogin::Contexts.from_example(RSpec.current_example)
78
- end
79
- end
80
- end
@@ -1,58 +0,0 @@
1
- module Xlogin
2
- module Contexts
3
-
4
- class << self
5
- def from_example(example)
6
- example_group = example.example_group
7
-
8
- node_resource = find_resource(Resources::NodeResource, example_group)
9
- command_resource = find_resource(Resources::CommandResource, example_group)
10
-
11
- return nil if node_resource.nil? && command_resource.nil?
12
- return NodeContext.new(node_resource.session) if command_resource.nil?
13
-
14
- CommandContext.new(node_resource.session, command_resource.text)
15
- end
16
-
17
- def find_resource(klass, example_group)
18
- arg = example_group.metadata[:description_args][0]
19
- return arg if arg.is_a?(klass)
20
-
21
- parent = example_group.parent_groups[1]
22
- find_resource(klass, parent) if parent
23
- end
24
- end
25
-
26
- class NodeContext
27
- attr_reader :session
28
-
29
- def initialize(session)
30
- @session = session
31
- end
32
-
33
- def name
34
- @session.name
35
- end
36
- end
37
-
38
- class CommandContext
39
- class << self
40
- def response_cache
41
- @cache ||= {}
42
- end
43
- end
44
-
45
- attr_reader :session, :command
46
-
47
- def initialize(session, command)
48
- @session = session
49
- @command = command
50
- end
51
-
52
- def response
53
- self.class.response_cache[[@session.name, @command]] ||= @session.cmd(@command)
54
- end
55
- end
56
-
57
- end
58
- end
@@ -1,31 +0,0 @@
1
- module Xlogin
2
- module Resources
3
-
4
- class NodeResource
5
- def initialize(name)
6
- @name = name
7
- end
8
-
9
- def session
10
- @session ||= Xlogin.get(@name)
11
- end
12
-
13
- def to_s
14
- "Node '#{session.name}'"
15
- end
16
- end
17
-
18
- class CommandResource
19
- attr_reader :text
20
-
21
- def initialize(text)
22
- @text = text
23
- end
24
-
25
- def to_s
26
- "with command '#{text}'"
27
- end
28
- end
29
-
30
- end
31
- end
@@ -1,88 +0,0 @@
1
- require 'xlogin'
2
- require 'xlogin/thread_safe'
3
-
4
- module Xlogin
5
-
6
- class Scanner
7
- class << self
8
- def login_opts(**opts)
9
- @login_opts = opts unless opts.empty?
10
- @login_opts || {}
11
- end
12
- end
13
-
14
- def initialize
15
- @sessions = Hash.new
16
- @scan_db = Hash.new
17
- @queries = Array.new
18
- end
19
-
20
- def ids
21
- @scan_db.keys
22
- end
23
-
24
- def sessions(&block)
25
- hostnames = @queries.map { |_, hostname, _| hostname }.uniq
26
- sessions = hostnames.map { |hostname| session(hostname) }
27
- sessions.each { |s| block.call(s) } if block
28
- sessions
29
- end
30
-
31
- def define(id, &block)
32
- type = ScanType.new
33
- type.instance_eval(&block)
34
-
35
- @scan_db[id] = type
36
- end
37
-
38
- def add(id, hostname, *args)
39
- @queries << [id, hostname, *args]
40
- end
41
-
42
- def scan
43
- data = Hash.new
44
- cache = Hash.new
45
-
46
- threads = @queries.map do |req_key|
47
- Thread.new do
48
- id, hostname, *args = *req_key
49
- type = @scan_db[id]
50
-
51
- command = type.command.call(*args)
52
- content = session(hostname).thread_safe { |s| s.cmd(command) }
53
- matched = type.scanner.call(content)
54
-
55
- cache[[hostname, command]] ||= content
56
- data[req_key] = matched
57
-
58
- yield(req_key, matched) if block_given?
59
- end
60
- end
61
- threads.each { |th| th.join }
62
-
63
- data
64
- end
65
-
66
- def close
67
- sessions { |s| s.close }
68
- end
69
-
70
- private
71
- def session(hostname)
72
- @sessions[hostname] ||= Xlogin.get(hostname, **Xlogin::Scanner.login_opts)
73
- end
74
- end
75
-
76
- class ScanType
77
- def command(val = nil, &block)
78
- return @command unless val || block
79
- @command = (val) ? lambda { val } : block
80
- end
81
-
82
- def scanner(&block)
83
- return @scanner unless block
84
- @scanner = block
85
- end
86
- end
87
-
88
- end
@@ -1,25 +0,0 @@
1
- require 'thread'
2
- require 'timeout'
3
-
4
- module Xlogin
5
- module Session
6
- def thread_safe(timeout: @timeout, maximum_retry: 1)
7
- @safe_session = self
8
- @safe_session_mutex ||= Mutex.new
9
-
10
- Timeout.timeout(timeout) do
11
- @safe_session_mutex.synchronize do
12
- retry_count = 0
13
- begin
14
- @safe_session ||= Xlogin.get(@host, @opts)
15
- yield @safe_session
16
- rescue Errno::ECONNRESET => e
17
- raise e unless (retry_count += 1) < maximum_retry
18
- @safe_session = nil
19
- retry
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end