expect4r 0.0.3.dev → 0.0.4.dev

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.
data/README.rdoc CHANGED
@@ -14,7 +14,13 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
14
14
 
15
15
  j = J.new_telnet :host=> '', :user=> 'lab', :pwd => 'lab'
16
16
  j.login
17
-
17
+
18
+ * Connect to a box via another
19
+
20
+ my_mac = RShell.new_ssh 'mac', 'me'
21
+ router = Iox.new_telnet 'hostname', 'username'
22
+ router.login_via my_mac
23
+
18
24
  * Push configurations to routers
19
25
 
20
26
  ios.config 'no logging console'
@@ -118,7 +124,7 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
118
124
  output[n-1] contains output for nth command.
119
125
 
120
126
 
121
- * Ping
127
+ * Ios Ping
122
128
 
123
129
  irb(main):016:0> ios.ping '192.168.1.23', :count=> 100, :pct_success=>90, :sweep_max_size=> 1500
124
130
  => [ 99, [146148, 146500],
@@ -144,6 +150,8 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
144
150
  "ios#"]]]
145
151
 
146
152
 
153
+ * Iox ping
154
+
147
155
  irb> iox.ping '192.168.1.100'
148
156
  => [100, [5, 5],
149
157
  [["ping 192.168.1.100",
@@ -178,3 +186,16 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
178
186
  "Success rate is 100 percent (1505/1505), round-trip min/avg/max = 1/1/3 ms",
179
187
  "RP/0/0/CPU0:Paris-rp0#"]]]
180
188
 
189
+
190
+ * Junos ping
191
+
192
+ irb> j.ping '192.168.1.123'
193
+ => [5, [5, 0],
194
+ [["ping 192.168.1.123 rapid ",
195
+ "PING 192.168.1.123 (192.168.1.123): 56 data bytes",
196
+ "!!!!!",
197
+ "--- 192.168.1.123 ping statistics ---",
198
+ "5 packets transmitted, 5 packets received, 0% packet loss",
199
+ "round-trip min/avg/max/stddev = 2.310/2.943/4.390/0.753 ms",
200
+ "",
201
+ junos> "]]]
data/examples/jex1.rb ADDED
@@ -0,0 +1,104 @@
1
+ require 'expect4r'
2
+ require "enumerator"
3
+ include Expect4r
4
+ include Expect4r::Router::Error
5
+
6
+ paris_config = %|
7
+ top
8
+ edit logical-router Paris interface fxp0 unit 25
9
+ set vlan-id 25
10
+ set family inet address 40.0.1.1/24
11
+ top
12
+ edit logical-router Paris interface fxp1 unit 22
13
+ set vlan-id 22
14
+ set family inet address 40.0.2.1/24
15
+ top
16
+ edit logical-router Paris interface lo0 unit 1
17
+ set family inet address 192.168.127.1/32
18
+ top
19
+ edit logical-router Paris interface fxp0 unit 24
20
+ set vlan-id 24
21
+ set family inet address 40.0.0.2/24
22
+ top
23
+ edit logical-router Paris
24
+ set routing-options autonomous-system 200
25
+ top
26
+ edit logical-router Paris protocols bgp
27
+ edit group session-to-300
28
+ set type external
29
+ set peer-as 300
30
+ set neighbor 40.0.1.2 peer-as 300
31
+ exit
32
+ edit group session-to-210
33
+ set type external
34
+ set peer-as 210
35
+ set neighbor 40.0.2.2 peer-as 210
36
+ exit
37
+ edit group session-to-100
38
+ set type external
39
+ set peer-as 100
40
+ set neighbor 40.0.0.1 peer-as 100
41
+ |
42
+
43
+ orleans_config = %|
44
+ top
45
+ edit logical-router Orleans interface fxp2 unit 22
46
+ set vlan-id 22
47
+ set family inet address 40.0.2.2/24
48
+ top
49
+ edit logical-router Orleans
50
+ set routing-options autonomous-system 100
51
+ top
52
+ edit logical-router Orleans protocols bgp
53
+ edit group session-to-200
54
+ set type external
55
+ set peer-as 200
56
+ set neighbor 40.0.2.1 peer-as 200
57
+ |
58
+
59
+ begin
60
+
61
+ paris = J.new_telnet('olive', 'jme').login
62
+ orleans = J.new_telnet('olive', 'jme').login
63
+
64
+ threads =[]
65
+ threads << Thread.new { paris.config paris_config }
66
+ threads << Thread.new { p orleans.config orleans_config }
67
+ threads.each { |th| th.join }
68
+
69
+ rescue ConnectionError => e
70
+
71
+ p 'CONNECTION ERROR'
72
+
73
+ puts e.err_msg
74
+
75
+ rescue SyntaxError, SemanticError => e
76
+
77
+ p 'CONFIG ERROR'
78
+ puts e.err_msg
79
+
80
+ else
81
+
82
+ begin
83
+
84
+ paris.ping '40.0.2.1', :logical_router=>'Paris', :count=>100
85
+ orleans.ping '40.0.2.2', :logical_router=>'Orleans', :count=>100
86
+
87
+ rescue PingError => e
88
+
89
+ p 'PING ERROR'
90
+ puts e.err_msg
91
+
92
+ end
93
+
94
+ ensure
95
+
96
+ [paris, orleans].each { |r| r.logout }
97
+
98
+ end
99
+
100
+
101
+
102
+
103
+
104
+
data/examples/jex2.rb ADDED
@@ -0,0 +1,88 @@
1
+ require "test/unit"
2
+ require 'expect4r'
3
+
4
+ class TestPingTest < Test::Unit::TestCase
5
+ include Expect4r
6
+ include Expect4r::Router::Error
7
+
8
+ def setup
9
+
10
+ paris_config = %|
11
+ top
12
+ edit logical-router Paris interface fxp0 unit 25
13
+ set vlan-id 25
14
+ set family inet address 40.0.1.1/24
15
+ top
16
+ edit logical-router Paris interface fxp1 unit 22
17
+ set vlan-id 22
18
+ set family inet address 40.0.2.1/24
19
+ top
20
+ edit logical-router Paris interface lo0 unit 1
21
+ set family inet address 192.168.127.1/32
22
+ top
23
+ edit logical-router Paris interface fxp0 unit 24
24
+ set vlan-id 24
25
+ set family inet address 40.0.0.2/24
26
+ top
27
+ edit logical-router Paris
28
+ set routing-options autonomous-system 200
29
+ top
30
+ edit logical-router Paris protocols bgp
31
+ edit group session-to-300
32
+ set type external
33
+ set peer-as 300
34
+ set neighbor 40.0.1.2 peer-as 300
35
+ exit
36
+ edit group session-to-210
37
+ set type external
38
+ set peer-as 210
39
+ set neighbor 40.0.2.2 peer-as 210
40
+ exit
41
+ edit group session-to-100
42
+ set type external
43
+ set peer-as 100
44
+ set neighbor 40.0.0.1 peer-as 100
45
+ |
46
+
47
+ orleans_config = %|
48
+ top
49
+ edit logical-router Orleans interface fxp2 unit 22
50
+ set vlan-id 22
51
+ set family inet address 40.0.2.2/24
52
+ top
53
+ edit logical-router Orleans
54
+ set routing-options autonomous-system 100
55
+ top
56
+ edit logical-router Orleans protocols bgp
57
+ edit group session-to-200
58
+ set type external
59
+ set peer-as 200
60
+ set neighbor 40.0.2.1 peer-as 200
61
+ |
62
+
63
+ @paris = J.new_ssh('olive', 'jesnault', 'HomeLab').login
64
+ @orleans = J.new_ssh('olive', 'jesnault', 'HomeLab').login
65
+ threads =[]
66
+ threads << Thread.new { @paris.config paris_config }
67
+ threads << Thread.new { @orleans.config orleans_config }
68
+ threads.each { |th| th.join }
69
+
70
+ end
71
+
72
+ def teardown
73
+ @paris.config "delete logical-routers"
74
+ [@paris, @orleans].each { |r| r.logout }
75
+ end
76
+
77
+ def test_ping_test
78
+ assert_nothing_raised(Exception) {
79
+ threads =[]
80
+ threads << Thread.new { @paris.ping '40.0.2.1', :logical_router=>'Paris', :count=>100 }
81
+ threads << Thread.new { @orleans.ping '40.0.2.2', :logical_router=>'Orleans', :count=>100 }
82
+ threads.each { |th| th.join }
83
+ }
84
+
85
+ end
86
+
87
+ end
88
+
data/lib/expect/io.rb CHANGED
@@ -230,12 +230,12 @@ module Expect4r
230
230
  @r.readbuf(timeout) do |read_pipe|
231
231
  if read_pipe._io_exit?
232
232
  exp_internal "readbuf: _io_exit?"
233
- throw :done, [ :abort, output]
233
+ throw :done, [ :cnx_error, read_pipe._io_buf1]
234
234
  end
235
235
  case read_pipe._io_string
236
236
  when spawnee_prompt
237
- read_pipe._io_save false, "match PROMPT"
238
- throw(:done, [:ok, output])
237
+ read_pipe._io_save no_echo, "match PROMPT"
238
+ throw(:done, [:ok, read_pipe._io_buf1])
239
239
  when /Last (L|l)ogin:/
240
240
  read_pipe._io_save no_echo # consumes
241
241
  when /(user\s*name\s*|login):\s*$/i
@@ -249,22 +249,22 @@ module Expect4r
249
249
  io_escape_char_cb
250
250
  when /.*\r\n/
251
251
  exp_internal "match EOL"
252
- read_pipe._io_save no_echo, "match EOL", "\r\n"
252
+ read_pipe._io_save no_echo, "match EOL"
253
253
  when /Are you sure you want to continue connecting \(yes\/no\)\?/
254
254
  read_pipe._io_save no_echo, "match continue connecting"
255
255
  exp_puts 'yes'
256
+ when /(Login incorrect|denied, please try again)/
257
+ spawnee_reset
256
258
  end
257
259
  end
258
260
  end
259
261
  case ev
260
- when :abort
261
- elapsed = Time.now - t0
262
- if elapsed < timeout
263
- child_exit
264
- raise ConnectionError.new(cmd)
265
- else
266
- raise ExpTimeoutError.new(cmd, timeout)
267
- end
262
+ when :cnx_error
263
+ child_exit
264
+ err_msg = "Could not connect to #{@host}:\n"
265
+ err_msg += " >> #{cmd}\n "
266
+ err_msg += buf.join("\n ")
267
+ raise ConnectionError.new(err_msg)
268
268
  else
269
269
  @lp = buf.last
270
270
  end
@@ -305,12 +305,12 @@ module Expect4r
305
305
  case r._io_string
306
306
  when @ps1, @ps1_bis
307
307
  unless r._io_more?
308
- r._io_save false, "matching PROMPT"
308
+ r._io_save no_echo, "matching PROMPT"
309
309
  throw(:done, [:ok, r._io_buf1])
310
310
  end
311
311
  exp_internal "more..."
312
312
  when /(.+)\r\n/, "\r\n"
313
- r._io_save no_echo, "matching EOL", "\r\n"
313
+ r._io_save no_echo, "matching EOL"
314
314
  when @more
315
315
  r._io_save no_echo, "matching MORE"
316
316
  putc ' '
@@ -433,9 +433,19 @@ end
433
433
  module Expect4r
434
434
  class BaseLoginObject
435
435
  class << self
436
+ # Examples:
437
+ # my_mac = RShell.new_telnet '1.1.1.1', 'me', 'secret'
438
+ # ios = Ios.new_telnet '1.1.1.1', 'lab', 'lab'
439
+ # iox = Iox.new_telnet '1.1.1.1', 'username', 'pwd'
440
+ #
436
441
  def new_telnet(*args)
437
442
  new :telnet, *args
438
443
  end
444
+ # Examples:
445
+ # my_mac = RShell.new_ssh '1.1.1.1', 'me', 'secret'
446
+ # iox = Ios.new_ssh '1.1.1.1', 'lab', 'lab'
447
+ # ios = Iosx.new_ssh '1.1.1.1', 'username', 'pwd'
448
+ #
439
449
  def new_ssh(*args)
440
450
  new :ssh, *args
441
451
  end
@@ -460,8 +470,9 @@ module Expect4r
460
470
  # * <tt>:pwd</tt> or <tt>:password</tt>
461
471
  #
462
472
  # Examples:
463
- # new :telnet, :user=> 'lab', :password=>'lab'
464
- # new :ssh, :user=> 'jme'
473
+ # new :telnet, :host=> '1.1.1.1', :user=> 'lab', :password=>'lab'
474
+ # new :ssh, :host=> '1.1.1.1', :user=> 'jme'
475
+ # new :ssh, '1.1.1.1', 'me', 'secret'
465
476
  #
466
477
  def initialize(*args)
467
478
  ciphered_password=nil
@@ -516,9 +527,16 @@ module Expect4r
516
527
  private
517
528
 
518
529
  def spawnee_password
519
- @pwd = Expect4r.cipher( ask("(#{self}) Enter your password: ") { |q| q.echo = "X" } ) unless @pwd
530
+ if @pwd.nil?
531
+ @pwd = Expect4r.cipher( ask("(#{self}) Enter your password: ") { |q| q.echo = "X" } )
532
+ @asked4pwd=true
533
+ end
520
534
  Expect4r.decipher(@pwd)
521
535
  end
536
+
537
+ def spawnee_reset
538
+ @pwd=nil if @asked4pwd
539
+ end
522
540
 
523
541
  end
524
542
  end
data/lib/expect4r.rb CHANGED
@@ -39,13 +39,3 @@ module Expect4r
39
39
  end
40
40
 
41
41
  end
42
-
43
- if __FILE__ == $0
44
- module Expect4r
45
- p Expect4r::Iox.new_ssh 'hostname', 'username'
46
- p Expect4r::Iox.new_telnet 'hostname', 'username'
47
- p Expect4r::Ios.new_ssh 'hostname', 'username'
48
- p Expect4r::J.new_ssh 'hostname', 'username'
49
- p Expect4r::Shell.new
50
- end
51
- end
data/lib/misc/shell.rb CHANGED
@@ -14,6 +14,7 @@ module Expect4r
14
14
  end
15
15
  class RShell < ::Expect4r::BaseLoginObject
16
16
  include Expect4r
17
+
17
18
  def initialize(*args)
18
19
  super
19
20
  default_ps1
@@ -35,7 +36,7 @@ module Expect4r
35
36
  # Assumes bash
36
37
  @ps1_bis = /#{val}$/
37
38
  cmd %? export PS1='#{val}' ?
38
- @ps1 = @ps1_bi
39
+ @ps1 = @ps1_bis
39
40
  end
40
41
  def cmd(*args)
41
42
  exp_send *args
@@ -66,14 +66,14 @@ module Modes
66
66
  end
67
67
 
68
68
  #
69
- # returns <tt>true</tt> if router is in <tt>:exec</tt> (enabled) mode, <tt>false</tt> otherwise.
69
+ # returns *true* if router is in <tt>:exec</tt> (enabled) mode, *false* otherwise.
70
70
  #
71
71
  def exec?
72
72
  ! user? and ! config?
73
73
  end
74
74
 
75
75
  #
76
- # returns <tt>true</tt> if router is in <tt>:user</tt> mode, <tt>false</tt> otherwise.
76
+ # returns *true* if router is in <tt>:user</tt> mode, *false* otherwise.
77
77
  #
78
78
  def user?
79
79
  @lp =~ /.+>\s*$/
@@ -3,7 +3,7 @@ require 'router/modes'
3
3
  module Expect4r::Router::Iox
4
4
  module Modes
5
5
 
6
- # Adds an Iox <tt>config>/tt> mixin.
6
+ # Adds an Iox <tt>config</tt> mixin.
7
7
  #
8
8
  # Options are:
9
9
  #
@@ -29,10 +29,16 @@ class Expect4r::J < ::Expect4r::BaseLoginObject
29
29
 
30
30
  def putline(line,arg={})
31
31
  o, rc = super
32
- raise SyntaxError.new(self.class.to_s, line) if o.join =~ /(unknown command|syntax error)\./
32
+ raise SyntaxError.new(self.class.to_s, line) if o.join =~ /(unknown command|syntax error)/
33
33
  o
34
34
  end
35
35
 
36
+ def rollback
37
+ return unless config?
38
+ top
39
+ putline 'rollback'
40
+ end
41
+
36
42
  def top
37
43
  putline 'top'
38
44
  end
@@ -46,7 +52,7 @@ class Expect4r::J < ::Expect4r::BaseLoginObject
46
52
  @matches << [/Exit with uncommitted changes.+\(yes\)/, 'yes']
47
53
  output = putline "commit", arg
48
54
  if /error: configuration check-out failed/.match(output.join)
49
- putline 'rollback'
55
+ rollack
50
56
  raise SemanticError.new(self.class.to_s, output)
51
57
  end
52
58
  output
@@ -23,7 +23,7 @@ def config(stmts=nil, arg={})
23
23
  output = exp_send(stmts, arg)
24
24
  output << commit
25
25
  change_mode_to(mode)
26
- output
26
+ output.flatten
27
27
  else
28
28
  to_config
29
29
  end
@@ -69,21 +69,21 @@ def shell(cmd=nil, *args)
69
69
  end
70
70
 
71
71
  #
72
- # returns <tt>true</tt> if router is in <tt>:exec</tt> mode, <tt>false</tt> otherwise.
72
+ # returns *true* if router is in <tt>:exec</tt> mode, *false* otherwise.
73
73
  #
74
74
  def exec?
75
75
  @lp =~ /> $/ ? true : false
76
76
  end
77
77
 
78
78
  #
79
- # returns <tt>true</tt> if router is in <tt>:config</tt> mode, <tt>false</tt> otherwise.
79
+ # returns *true* if router is in <tt>:config</tt> mode, *false* otherwise.
80
80
  #
81
81
  def config?
82
82
  @lp =~ /^.+# $/ ? true : false
83
83
  end
84
84
 
85
85
  #
86
- # returns <tt>true</tt> if router is in <tt>:shell</tt> mode, <tt>false</tt> otherwise.
86
+ # returns *true* if router is in <tt>:shell</tt> mode, *false* otherwise.
87
87
  #
88
88
  def shell?
89
89
  @lp == '% ' ? true : false
@@ -27,7 +27,7 @@ module Ping
27
27
 
28
28
  output = exec(ping_cmd(host, arg), arg)
29
29
 
30
- r = output[0].find { |x| p x ; x =~/(\d+) packets transmitted, (\d+) packets received, (\d+)\% packet loss/}
30
+ r = output[0].find { |x| x =~/(\d+) packets transmitted, (\d+) packets received, (\d+)\% packet loss/}
31
31
 
32
32
  if r &&
33
33
  Regexp.last_match(1) &&
@@ -55,6 +55,7 @@ private
55
55
  def ping_cmd(host, arg={})
56
56
  cmd = "ping #{host}"
57
57
  cmd += " rapid"
58
+ cmd += " logical-router #{arg[:logical_router]}" if arg[:logical_router]
58
59
  cmd += " count #{arg[:count] || arg[:repeat_count]}" if arg[:count] || arg[:repeat_count]
59
60
  cmd += " size #{arg[:size] || arg[:datagram_size]}" if arg[:size] || arg[:datagram_size]
60
61
  cmd += " pattern #{arg[:pattern]}" if arg[:pattern]
data/lib/router/modes.rb CHANGED
@@ -7,16 +7,17 @@ module Modes
7
7
  #
8
8
  # Examples:
9
9
  #
10
- # irb(main):007:0> iox.in?
11
- # => :exec
12
- # irb(main):008:0> iox.config
13
- # => :config
14
- # irb(main):009:0> iox.in?
15
- # => :config
16
- # irb(main):010:0> iox.shell
17
- # => :shell
18
- # irb(main):011:0> iox.in?
19
- # => :shell
10
+ # >> iox.in?
11
+ # => *:exec*
12
+ # >> iox.config
13
+ # => *:config*
14
+ # >> iox.in?
15
+ # => *:config*
16
+ # >> iox.shell
17
+ # => *:shell*
18
+ # >> iox.in?
19
+ # => *:shell*
20
+ #
20
21
  def in?(mode=:none)
21
22
  login unless connected?
22
23
  case mode
@@ -0,0 +1,12 @@
1
+ require 'expect4r'
2
+ require "test/unit"
3
+ class TestAutoload < Test::Unit::TestCase
4
+ include Expect4r
5
+ def test_autoload
6
+ assert Expect4r::Iox.new_ssh 'hostname', 'username'
7
+ assert Expect4r::Iox.new_telnet 'hostname', 'username'
8
+ assert Expect4r::Ios.new_ssh 'hostname', 'username'
9
+ assert Expect4r::J.new_ssh 'hostname', 'username'
10
+ assert Expect4r::Shell.new
11
+ end
12
+ end
@@ -1,8 +1,8 @@
1
+ require 'expect4r'
1
2
  require "test/unit"
2
3
 
3
- require "router/cisco/iox/iox"
4
-
5
4
  class TestRouterCiscoIoxIox < Test::Unit::TestCase
5
+ include Expect4r
6
6
  def test_new_hash_terse
7
7
  x = Iox.new :ssh,
8
8
  :host=> '1.1.1.1',
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - dev
10
- version: 0.0.3.dev
10
+ version: 0.0.4.dev
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jean-Michel Esnault
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-27 00:00:00 -07:00
18
+ date: 2010-10-30 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -45,6 +45,8 @@ files:
45
45
  - COPYING
46
46
  - LICENSE
47
47
  - README.rdoc
48
+ - examples/jex1.rb
49
+ - examples/jex2.rb
48
50
  - lib/expect/io.rb
49
51
  - lib/expect4r.rb
50
52
  - lib/misc/passwd.rb
@@ -84,8 +86,8 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
86
  segments:
85
87
  - 1
86
88
  - 8
87
- - 7
88
- version: 1.8.7
89
+ - 6
90
+ version: 1.8.6
89
91
  required_rubygems_version: !ruby/object:Gem::Requirement
90
92
  requirements:
91
93
  - - ">"
@@ -103,5 +105,6 @@ signing_key:
103
105
  specification_version: 3
104
106
  summary: Expect4r
105
107
  test_files:
108
+ - test/expect4r_test.rb
106
109
  - test/misc/passwd_test.rb
107
110
  - test/router/cisco/iox/iox_test.rb