train-core 2.0.8 → 2.0.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6296676d2fb3138e2e4e3f660e6bc9d871f10419318ba3344ca472c1eca7f0d2
4
- data.tar.gz: 8c5d1f00ee0c1e4dffa9520c8c622cd5333716a90576d52dfc5856f2ce7bf6de
3
+ metadata.gz: 6428f10f1fcb461fff9d6a262ed8a8c643ca0aaf21cc60a0ddeff1573f4e3c0e
4
+ data.tar.gz: a1d8450b00960078fb2116ec40dd3f1e61a5976a4aa6aa14e4c0a3e73596f27b
5
5
  SHA512:
6
- metadata.gz: 97150adffc1f18041eb3c1f7c77c439920674a2f1d40ef90b7720eeb808bc98709d4cd646af0fae949a47229703dc19988ac2ca54b21e1de5aeb2b71a873a4d1
7
- data.tar.gz: '028b9286800362e7e945c6fa5d3efde308e5b917233e7e9367b00ba289e87902ac4a8ccfcb55bf6879d7548340a40156e0cf2a05035c139d86d216dd27bda036'
6
+ metadata.gz: 338cd5ee7abda4182c71c3132336b647ab5353d90934673fdf156577506167e109e557b6c139288b5dcc89476742a34eb692b95bfd99ad7159775f531f90c3ee
7
+ data.tar.gz: d15361a0bc4362272ea783c5198dea4ef6dbb5beb1a3878e04eb4484126f0b5daa2fdb0dbe725b5828da9cf48519f3d43730860a5a4e7de3ceaac7284b13f765
@@ -0,0 +1,128 @@
1
+ # encoding: utf-8
2
+
3
+ class Train::Transports::SSH
4
+ class CiscoIOSConnection < BaseConnection
5
+ class BadEnablePassword < Train::TransportError; end
6
+
7
+ def initialize(options)
8
+ super(options)
9
+
10
+ # Extract options to avoid passing them in to `Net::SSH.start` later
11
+ @host = options.delete(:host)
12
+ @user = options.delete(:user)
13
+ @port = options.delete(:port)
14
+ @enable_password = options.delete(:enable_password)
15
+
16
+ # Use all options left that are not `nil` for `Net::SSH.start` later
17
+ @ssh_options = options.reject { |_key, value| value.nil? }
18
+
19
+ @prompt = /^\S+[>#]\r\n.*$/
20
+ end
21
+
22
+ def uri
23
+ "ssh://#{@user}@#{@host}:#{@port}"
24
+ end
25
+
26
+ def unique_identifier
27
+ result = run_command_via_connection('show version | include Processor')
28
+ result.stdout.split(' ')[-1]
29
+ end
30
+
31
+ private
32
+
33
+ def establish_connection
34
+ logger.debug("[SSH] opening connection to #{self}")
35
+
36
+ Net::SSH.start(@host, @user, @ssh_options)
37
+ end
38
+
39
+ def session
40
+ return @session unless @session.nil?
41
+
42
+ @session = open_channel(establish_connection)
43
+
44
+ # Escalate privilege to enable mode if password is given
45
+ if @enable_password
46
+ # This verifies we are not in privileged exec mode before running the
47
+ # enable command. Otherwise, the password will be in history.
48
+ if run_command_via_connection('show privilege').stdout.split[-1] != '15'
49
+ run_command_via_connection("enable\r\n#{@enable_password}")
50
+ end
51
+ end
52
+
53
+ # Prevent `--MORE--` by removing terminal length limit
54
+ run_command_via_connection('terminal length 0')
55
+
56
+ @session
57
+ end
58
+
59
+ def run_command_via_connection(cmd, &_data_handler)
60
+ # Ensure buffer is empty before sending data
61
+ @buf = ''
62
+
63
+ logger.debug("[SSH] Running `#{cmd}` on #{self}")
64
+ session.send_data(cmd + "\r\n")
65
+
66
+ logger.debug('[SSH] waiting for prompt')
67
+ until @buf =~ @prompt
68
+ raise BadEnablePassword if @buf =~ /Bad secrets/
69
+ session.connection.process(0)
70
+ end
71
+
72
+ # Save the buffer and clear it for the next command
73
+ output = @buf.dup
74
+ @buf = ''
75
+
76
+ format_result(format_output(output, cmd))
77
+ end
78
+
79
+ ERROR_MATCHERS = [
80
+ 'Bad IP address',
81
+ 'Incomplete command',
82
+ 'Invalid input detected',
83
+ 'Unrecognized host',
84
+ ].freeze
85
+
86
+ # IOS commands do not have an exit code so we must compare the command
87
+ # output with partial segments of known errors. Then, we return a
88
+ # `CommandResult` with arguments in the correct position based on the
89
+ # result.
90
+ def format_result(result)
91
+ if ERROR_MATCHERS.none? { |e| result.include?(e) }
92
+ CommandResult.new(result, '', 0)
93
+ else
94
+ CommandResult.new('', result, 1)
95
+ end
96
+ end
97
+
98
+ # The buffer (@buf) contains all data sent/received on the SSH channel so
99
+ # we need to format the data to match what we would expect from Train
100
+ def format_output(output, cmd)
101
+ leading_prompt = /(\r\n|^)\S+[>#]/
102
+ command_string = /#{Regexp.quote(cmd)}\r\n/
103
+ trailing_prompt = /\S+[>#](\r\n|$)/
104
+ trailing_line_endings = /(\r\n)+$/
105
+
106
+ output
107
+ .sub(leading_prompt, '')
108
+ .sub(command_string, '')
109
+ .gsub(trailing_prompt, '')
110
+ .gsub(trailing_line_endings, '')
111
+ end
112
+
113
+ # Create an SSH channel that writes to @buf when data is received
114
+ def open_channel(ssh)
115
+ logger.debug("[SSH] opening SSH channel to #{self}")
116
+ ssh.open_channel do |ch|
117
+ ch.on_data do |_, data|
118
+ @buf += data
119
+ end
120
+
121
+ ch.send_channel_request('shell') do |_, success|
122
+ raise 'Failed to open SSH shell' unless success
123
+ logger.debug('[SSH] shell opened')
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
data/lib/train/version.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  # Author:: Dominik Richter (<dominik.richter@gmail.com>)
4
4
 
5
5
  module Train
6
- VERSION = '2.0.8'.freeze
6
+ VERSION = '2.0.12'.freeze
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: train-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.8
4
+ version: 2.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-19 00:00:00.000000000 Z
11
+ date: 2019-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -90,34 +90,6 @@ dependencies:
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
92
  version: '3.0'
93
- - !ruby/object:Gem::Dependency
94
- name: ed25519
95
- requirement: !ruby/object:Gem::Requirement
96
- requirements:
97
- - - "~>"
98
- - !ruby/object:Gem::Version
99
- version: '1.2'
100
- type: :runtime
101
- prerelease: false
102
- version_requirements: !ruby/object:Gem::Requirement
103
- requirements:
104
- - - "~>"
105
- - !ruby/object:Gem::Version
106
- version: '1.2'
107
- - !ruby/object:Gem::Dependency
108
- name: bcrypt_pbkdf
109
- requirement: !ruby/object:Gem::Requirement
110
- requirements:
111
- - - "~>"
112
- - !ruby/object:Gem::Version
113
- version: '1.0'
114
- type: :runtime
115
- prerelease: false
116
- version_requirements: !ruby/object:Gem::Requirement
117
- requirements:
118
- - - "~>"
119
- - !ruby/object:Gem::Version
120
- version: '1.0'
121
93
  - !ruby/object:Gem::Dependency
122
94
  name: winrm
123
95
  requirement: !ruby/object:Gem::Requirement
@@ -187,6 +159,7 @@ files:
187
159
  - lib/train/plugins.rb
188
160
  - lib/train/plugins/base_connection.rb
189
161
  - lib/train/plugins/transport.rb
162
+ - lib/train/transports/cisco_ios_connection.rb
190
163
  - lib/train/transports/local.rb
191
164
  - lib/train/transports/mock.rb
192
165
  - lib/train/transports/ssh.rb
@@ -206,7 +179,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
206
179
  requirements:
207
180
  - - ">="
208
181
  - !ruby/object:Gem::Version
209
- version: '0'
182
+ version: '2.4'
210
183
  required_rubygems_version: !ruby/object:Gem::Requirement
211
184
  requirements:
212
185
  - - ">="