expectacle 0.0.4 → 0.0.5
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/.rubocop.yml +4 -0
- data/.rubocop_todo.yml +2 -7
- data/Gemfile +2 -2
- data/README.md +27 -3
- data/Rakefile +4 -4
- data/expectacle.gemspec +1 -2
- data/lib/expectacle/thrower.rb +15 -41
- data/lib/expectacle/thrower_base.rb +10 -115
- data/lib/expectacle/thrower_base_io.rb +68 -0
- data/lib/expectacle/thrower_base_params.rb +80 -0
- data/lib/expectacle/thrower_preview.rb +60 -0
- data/lib/expectacle/thrower_utils.rb +35 -0
- data/lib/expectacle/version.rb +1 -1
- data/vendor/commands/cisco_show_version.yml +4 -0
- data/vendor/hosts/l2switch.yml +6 -5
- data/vendor/opts/cu_opts.yml +2 -0
- data/vendor/{ssh_opts.yml → opts/ssh_opts.yml} +0 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a27f91b34aba3a57cd043c6114aab2f7156ab77b
|
4
|
+
data.tar.gz: 8b10c0d7612d062d73a60bd1cfb5831f1d47cf7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e50f612f54dd268b7c1a029f9ee154ed93ac00e309ad837b958f9ab3443b526704cbbd8eac15cd5cc4d94db978a7cf6520f1349b7e1d7178877fcfb742029ff4
|
7
|
+
data.tar.gz: 3204c24a65f8af707e13c14744cf442c94b8fddc9212308d82bf5f7e201d5fe9ae122180c0eba4458b20ba8043b5238471d7695ea6d332e7b9eb3172bf32b9b6
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -10,18 +10,13 @@
|
|
10
10
|
Metrics/AbcSize:
|
11
11
|
Max: 18
|
12
12
|
|
13
|
-
# Offense count: 2
|
14
|
-
# Configuration parameters: CountComments.
|
15
|
-
Metrics/ClassLength:
|
16
|
-
Max: 140
|
17
|
-
|
18
13
|
# Offense count: 1
|
19
14
|
# Configuration parameters: CountComments.
|
20
15
|
Metrics/MethodLength:
|
21
|
-
Max:
|
16
|
+
Max: 15
|
22
17
|
|
23
18
|
# Offense count: 1
|
24
19
|
# Configuration parameters: AllowedVariables.
|
25
20
|
Style/GlobalVars:
|
26
21
|
Exclude:
|
27
|
-
- 'lib/expectacle/thrower_base.rb'
|
22
|
+
- 'lib/expectacle/thrower_base.rb' # $expect_verbose
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -211,10 +211,10 @@ For example, if you want to save configuration of a Cisco device to tftp server:
|
|
211
211
|
- "copy run tftp://<%= @host_param[:tftp_server] %>/<%= @host_param[:hostname] %>.confg"
|
212
212
|
```
|
213
213
|
|
214
|
-
## SSH Options
|
214
|
+
## Default SSH Options
|
215
215
|
|
216
|
-
When use `ssh` (OpenSSH) command to spawn device, the user can set options for the command via `#{base_dir}/ssh_opts.yml`.
|
217
|
-
With options as list in [ssh_opts.yml](./vendor/ssh_opts.yml),
|
216
|
+
When use `ssh` (OpenSSH) command to spawn device, the user can set options for the command via `#{base_dir}/opts/ssh_opts.yml`.
|
217
|
+
With options as list in [ssh_opts.yml](./vendor/opts/ssh_opts.yml),
|
218
218
|
```
|
219
219
|
- '-o StrictHostKeyChecking=no'
|
220
220
|
- '-o KexAlgorithms=+diffie-hellman-group1-sha1'
|
@@ -228,6 +228,30 @@ Host *
|
|
228
228
|
Ciphers +aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc
|
229
229
|
```
|
230
230
|
|
231
|
+
## Use Local Serial Console
|
232
|
+
|
233
|
+
Expectacle can handle `cu` (call up another system) command to operate via device local serial port.
|
234
|
+
|
235
|
+
If you use Ubuntu, install `cu` at first.
|
236
|
+
```
|
237
|
+
sudo apt install cu
|
238
|
+
```
|
239
|
+
|
240
|
+
Set parameter `:protocol` to `cu`, and write `cu` command options as `:cu_opts`. Usually, one serial port correspond to one device. So host parameter `:cu_opts` is used as options to connect a host via serial port. For example:
|
241
|
+
```
|
242
|
+
- :hostname : 'l2sw1'
|
243
|
+
:type : 'c3750g'
|
244
|
+
:protocol : 'cu'
|
245
|
+
:cu_opts : '-l /dev/ttyUSB0 -s 9600'
|
246
|
+
```
|
247
|
+
File `#{base_dir}/opts/cu_opts.yml` has default options for `cu` command.
|
248
|
+
|
249
|
+
At last, execute by `run_command` with `sudo`. Because it requires superuser permission to handle local device.
|
250
|
+
```
|
251
|
+
sudo -E bundle exec run_command -r -h l2switch.yml -c cisco_show_version.yml
|
252
|
+
```
|
253
|
+
**Notice** : Without `sudo -E` (`--preserve-env`) option, it do not preserve environment variables such as username/password and others you defined.
|
254
|
+
|
231
255
|
## TODO
|
232
256
|
|
233
257
|
### Sub prompt operation (interactive command)
|
data/Rakefile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
-
task default: [
|
2
|
+
task default: %i[spec rubocop]
|
3
3
|
|
4
4
|
begin
|
5
5
|
require 'rspec/core/rake_task'
|
6
6
|
RSpec::Core::RakeTask.new
|
7
7
|
rescue LoadError
|
8
8
|
task :spec do
|
9
|
-
|
9
|
+
warn 'RSpec is disabled'
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -15,7 +15,7 @@ begin
|
|
15
15
|
RuboCop::RakeTask.new
|
16
16
|
rescue LoadError
|
17
17
|
task :rubocop do
|
18
|
-
|
18
|
+
warn 'RuboCop is disabled'
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -27,6 +27,6 @@ begin
|
|
27
27
|
end
|
28
28
|
rescue LoadError
|
29
29
|
task :yard do
|
30
|
-
|
30
|
+
warn 'YARD is disabled'
|
31
31
|
end
|
32
32
|
end
|
data/expectacle.gemspec
CHANGED
data/lib/expectacle/thrower.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'expectacle/
|
3
|
+
require 'expectacle/thrower_preview'
|
4
|
+
require 'expectacle/thrower_utils'
|
4
5
|
|
5
6
|
module Expectacle
|
7
|
+
# Maximum number to retly authentication
|
8
|
+
MAX_AUTH_COUNT = 10
|
9
|
+
|
6
10
|
# Thrower logic(command list operation)
|
7
11
|
class Thrower < ThrowerBase
|
8
12
|
# Run(exec) commands for all hosts.
|
@@ -11,35 +15,29 @@ module Expectacle
|
|
11
15
|
def run_command_for_all_hosts(hosts, commands)
|
12
16
|
hosts.each do |each|
|
13
17
|
@commands = commands.dup # Notice: @commands will be decremented.
|
18
|
+
@commands_len = @commands.length
|
19
|
+
@auth_count = 0
|
14
20
|
@host_param = each
|
15
21
|
run_command_for_host
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
19
|
-
# Preview all parameters for all hosts.
|
20
|
-
# @param [Array<Hash>] hosts Host parameters (read from host list file).
|
21
|
-
# @param [Array<String>] commands Commands (read from command list file).
|
22
|
-
def preview_parameter(hosts, commands)
|
23
|
-
@commands = commands
|
24
|
-
hosts.each do |each|
|
25
|
-
@host_param = each
|
26
|
-
preview_command_for_host
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
25
|
private
|
31
26
|
|
32
27
|
def run_command_for_host
|
33
28
|
ready_to_open_host_session do |spawn_cmd|
|
34
29
|
open_interactive_process(spawn_cmd) do
|
30
|
+
before_run_command
|
35
31
|
run_command
|
36
32
|
end
|
37
33
|
end
|
38
34
|
end
|
39
35
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
36
|
+
def before_run_command
|
37
|
+
return unless @local_serial
|
38
|
+
# for `cu` command
|
39
|
+
@reader.expect(/^Connected\./, 1) do
|
40
|
+
write_and_logging 'Send enter to connect serial', "\r\n", true
|
43
41
|
end
|
44
42
|
end
|
45
43
|
|
@@ -50,36 +48,11 @@ module Expectacle
|
|
50
48
|
end
|
51
49
|
end
|
52
50
|
|
53
|
-
def previewed_host_param
|
54
|
-
host_param = @host_param.dup
|
55
|
-
enable_mode = @enable_mode
|
56
|
-
@enable_mode = false
|
57
|
-
host_param[:username] = embed_user_name
|
58
|
-
host_param[:password] = embed_password
|
59
|
-
@enable_mode = true
|
60
|
-
host_param[:enable] = embed_password
|
61
|
-
@enable_mode = enable_mode
|
62
|
-
host_param
|
63
|
-
end
|
64
|
-
|
65
|
-
def previewed_commands
|
66
|
-
@commands.map { |cmd| embed_command(cmd) }
|
67
|
-
end
|
68
|
-
|
69
|
-
def whole_previewed_parameters(spawn_cmd)
|
70
|
-
{
|
71
|
-
spawn_cmd: spawn_cmd,
|
72
|
-
prompt: @prompt,
|
73
|
-
host: previewed_host_param,
|
74
|
-
commands: previewed_commands
|
75
|
-
}
|
76
|
-
end
|
77
|
-
|
78
51
|
def exec_rest_commands
|
79
52
|
if !@commands.empty?
|
80
53
|
yield
|
81
54
|
else
|
82
|
-
|
55
|
+
close_session
|
83
56
|
end
|
84
57
|
end
|
85
58
|
|
@@ -118,6 +91,7 @@ module Expectacle
|
|
118
91
|
end
|
119
92
|
|
120
93
|
def exec_each_prompt(prompt)
|
94
|
+
check_auth_count
|
121
95
|
case prompt
|
122
96
|
when /#{@prompt[:password]}/, /#{@prompt[:enable_password]}/
|
123
97
|
write_and_logging 'Send password', embed_password, true
|
@@ -2,16 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'pty'
|
4
4
|
require 'expect'
|
5
|
-
require '
|
6
|
-
require '
|
7
|
-
require 'logger'
|
8
|
-
require 'syslog/logger'
|
5
|
+
require 'expectacle/thrower_base_io'
|
6
|
+
require 'expectacle/thrower_base_params'
|
9
7
|
|
10
8
|
module Expectacle
|
11
9
|
# Basic state setup/management
|
12
10
|
class ThrowerBase
|
13
|
-
# @return [Logger] Logger instance.
|
14
|
-
attr_accessor :logger
|
15
11
|
# @return [String] Base directory path to find params/hosts/commands file.
|
16
12
|
attr_reader :base_dir
|
17
13
|
|
@@ -58,31 +54,17 @@ module Expectacle
|
|
58
54
|
File.join @base_dir, 'commands'
|
59
55
|
end
|
60
56
|
|
61
|
-
|
62
|
-
|
63
|
-
def
|
64
|
-
|
65
|
-
logger.progname = progname
|
66
|
-
logger.datetime_format = '%Y-%m-%d %H:%M:%D %Z'
|
67
|
-
logger
|
57
|
+
# Path to span command options file directory.
|
58
|
+
# @return [String]
|
59
|
+
def opts_dir
|
60
|
+
File.join @base_dir, 'opts'
|
68
61
|
end
|
69
62
|
|
70
|
-
|
71
|
-
progname = 'Expectacle'
|
72
|
-
@logger = if logger == :syslog
|
73
|
-
Syslog::Logger.new(progname)
|
74
|
-
else
|
75
|
-
default_io_logger(logger, progname)
|
76
|
-
end
|
77
|
-
@logger.level = Logger::INFO
|
78
|
-
@logger.formatter = proc do |severity, datetime, pname, msg|
|
79
|
-
"#{datetime} #{pname} [#{severity}] #{msg}\n"
|
80
|
-
end
|
81
|
-
end
|
63
|
+
private
|
82
64
|
|
83
65
|
def ready_to_open_host_session
|
84
|
-
#
|
85
|
-
load_prompt_file
|
66
|
+
@local_serial = false # default for host
|
67
|
+
load_prompt_file # prompt regexp of device
|
86
68
|
spawn_cmd = make_spawn_command
|
87
69
|
if @prompt && spawn_cmd
|
88
70
|
yield spawn_cmd
|
@@ -92,7 +74,7 @@ module Expectacle
|
|
92
74
|
end
|
93
75
|
|
94
76
|
def do_on_interactive_process
|
95
|
-
until @reader.eof?
|
77
|
+
until @reader.closed? || @reader.eof?
|
96
78
|
@reader.expect(expect_regexp, @timeout) do |match|
|
97
79
|
yield match
|
98
80
|
end
|
@@ -111,93 +93,6 @@ module Expectacle
|
|
111
93
|
@writer.sync = true
|
112
94
|
yield
|
113
95
|
end
|
114
|
-
@logger.info "End spawn: #{@host_param[:hostname]}"
|
115
|
-
end
|
116
|
-
|
117
|
-
def ssh_command
|
118
|
-
opts = load_ssh_opts_file
|
119
|
-
['ssh', opts, "-l #{embed_user_name}", embed_ipaddr].join(' ')
|
120
|
-
end
|
121
|
-
|
122
|
-
def make_spawn_command
|
123
|
-
case @host_param[:protocol]
|
124
|
-
when /^telnet$/i
|
125
|
-
['telnet', embed_ipaddr].join(' ')
|
126
|
-
when /^ssh$/i
|
127
|
-
ssh_command
|
128
|
-
else
|
129
|
-
@logger.error "Unknown protocol #{@host_param[:protocol]}"
|
130
|
-
nil
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def load_yaml_file(file_type, file_name)
|
135
|
-
YAML.load_file file_name
|
136
|
-
rescue StandardError => error
|
137
|
-
@logger.error "Cannot load #{file_type}: #{file_name}"
|
138
|
-
raise error
|
139
|
-
end
|
140
|
-
|
141
|
-
def load_prompt_file
|
142
|
-
prompt_file = "#{prompts_dir}/#{@host_param[:type]}_prompt.yml"
|
143
|
-
@prompt = load_yaml_file('prompt file', prompt_file)
|
144
|
-
end
|
145
|
-
|
146
|
-
def load_ssh_opts_file
|
147
|
-
ssh_opts_file = "#{@base_dir}/ssh_opts.yml"
|
148
|
-
@ssh_opts = load_yaml_file('ssh opts file', ssh_opts_file)
|
149
|
-
end
|
150
|
-
|
151
|
-
def expect_regexp
|
152
|
-
/
|
153
|
-
( #{@prompt[:password]} | #{@prompt[:enable_password]}
|
154
|
-
| #{@prompt[:username]}
|
155
|
-
| #{@prompt[:command1]} | #{@prompt[:command2]}
|
156
|
-
| #{@prompt[:sub1]} | #{@prompt[:sub2]}
|
157
|
-
| #{@prompt[:yn]}
|
158
|
-
)\s*$
|
159
|
-
/x
|
160
|
-
end
|
161
|
-
|
162
|
-
def write_and_logging(message, command, secret = false)
|
163
|
-
logging_message = secret ? message : message + command
|
164
|
-
@logger.info logging_message
|
165
|
-
@writer.puts command
|
166
|
-
end
|
167
|
-
|
168
|
-
def check_embed_envvar(command)
|
169
|
-
return unless command =~ /<%=\s*ENV\[[\'\"]?(.+)[\'\"]\]?\s*%>/
|
170
|
-
envvar_name = Regexp.last_match(1)
|
171
|
-
if !ENV.key?(envvar_name)
|
172
|
-
@logger.error "Variable name: #{envvar_name} is not found in ENV"
|
173
|
-
elsif ENV[envvar_name] =~ /^\s*$/
|
174
|
-
@logger.warn "Env var: #{envvar_name} exists, but null string"
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def embed_password
|
179
|
-
@host_param[:enable] = '_NOT_DEFINED_' unless @host_param.key?(:enable)
|
180
|
-
base_str = @enable_mode ? @host_param[:enable] : @host_param[:password]
|
181
|
-
check_embed_envvar(base_str)
|
182
|
-
passwd_erb = ERB.new(base_str)
|
183
|
-
passwd_erb.result(binding)
|
184
|
-
end
|
185
|
-
|
186
|
-
def embed_command(command)
|
187
|
-
command_erb = ERB.new(command)
|
188
|
-
command_erb.result(binding)
|
189
|
-
end
|
190
|
-
|
191
|
-
def embed_user_name
|
192
|
-
check_embed_envvar(@host_param[:username])
|
193
|
-
uname_erb = ERB.new(@host_param[:username])
|
194
|
-
uname_erb.result(binding)
|
195
|
-
end
|
196
|
-
|
197
|
-
def embed_ipaddr
|
198
|
-
check_embed_envvar(@host_param[:ipaddr])
|
199
|
-
ipaddr_erb = ERB.new(@host_param[:ipaddr])
|
200
|
-
ipaddr_erb.result(binding)
|
201
96
|
end
|
202
97
|
end
|
203
98
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'logger'
|
5
|
+
require 'syslog/logger'
|
6
|
+
|
7
|
+
module Expectacle
|
8
|
+
# Basic state setup/management
|
9
|
+
class ThrowerBase
|
10
|
+
# @return [Logger] Logger instance.
|
11
|
+
attr_accessor :logger
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def write_and_logging(message, command, secret = false)
|
16
|
+
logging_message = secret ? message : message + command
|
17
|
+
@logger.info logging_message
|
18
|
+
if @writer.closed?
|
19
|
+
@logger.error "Try to write #{command}, but writer closed"
|
20
|
+
@commands.clear
|
21
|
+
else
|
22
|
+
@writer.puts command
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def default_io_logger(logger_io, progname)
|
27
|
+
logger = Logger.new(logger_io)
|
28
|
+
logger.progname = progname
|
29
|
+
logger.datetime_format = '%Y-%m-%d %H:%M:%D %Z'
|
30
|
+
logger
|
31
|
+
end
|
32
|
+
|
33
|
+
def setup_default_logger(logger)
|
34
|
+
progname = 'Expectacle'
|
35
|
+
@logger = if logger == :syslog
|
36
|
+
Syslog::Logger.new(progname)
|
37
|
+
else
|
38
|
+
default_io_logger(logger, progname)
|
39
|
+
end
|
40
|
+
@logger.level = Logger::INFO
|
41
|
+
@logger.formatter = proc do |severity, datetime, pname, msg|
|
42
|
+
"#{datetime} #{pname} [#{severity}] #{msg}\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def load_yaml_file(file_type, file_name)
|
47
|
+
YAML.load_file file_name
|
48
|
+
rescue StandardError => error
|
49
|
+
@logger.error "Cannot load #{file_type}: #{file_name}"
|
50
|
+
raise error
|
51
|
+
end
|
52
|
+
|
53
|
+
def load_prompt_file
|
54
|
+
prompt_file = "#{prompts_dir}/#{@host_param[:type]}_prompt.yml"
|
55
|
+
@prompt = load_yaml_file('prompt file', prompt_file)
|
56
|
+
end
|
57
|
+
|
58
|
+
def load_spawn_command_opts_file
|
59
|
+
opts_file = "#{opts_dir}/#{@host_param[:protocol]}_opts.yml"
|
60
|
+
if File.exist?(opts_file)
|
61
|
+
load_yaml_file("#{@host_param[:protocol]} opts file", opts_file)
|
62
|
+
else
|
63
|
+
@logger.warn "Opts file #{opts_file} not found."
|
64
|
+
[]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Expectacle
|
6
|
+
# Basic state setup/management
|
7
|
+
class ThrowerBase
|
8
|
+
private
|
9
|
+
|
10
|
+
def ssh_command
|
11
|
+
opts = load_spawn_command_opts_file
|
12
|
+
['ssh', opts, "-l #{embed_user_name}", embed_ipaddr].join(' ')
|
13
|
+
end
|
14
|
+
|
15
|
+
def cu_command
|
16
|
+
@local_serial = true
|
17
|
+
opts = load_spawn_command_opts_file
|
18
|
+
['cu', @host_param[:cu_opts], opts].join(' ')
|
19
|
+
end
|
20
|
+
|
21
|
+
def expect_regexp
|
22
|
+
/
|
23
|
+
( #{@prompt[:password]} | #{@prompt[:enable_password]}
|
24
|
+
| #{@prompt[:username]}
|
25
|
+
| #{@prompt[:command1]} | #{@prompt[:command2]}
|
26
|
+
| #{@prompt[:sub1]} | #{@prompt[:sub2]}
|
27
|
+
| #{@prompt[:yn]}
|
28
|
+
)\s*$
|
29
|
+
/x
|
30
|
+
end
|
31
|
+
|
32
|
+
def make_spawn_command
|
33
|
+
case @host_param[:protocol]
|
34
|
+
when /^telnet$/i
|
35
|
+
['telnet', embed_ipaddr].join(' ')
|
36
|
+
when /^ssh$/i
|
37
|
+
ssh_command
|
38
|
+
when /^cu$/i
|
39
|
+
cu_command
|
40
|
+
else
|
41
|
+
@logger.error "Unknown protocol #{@host_param[:protocol]}"
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def check_embed_envvar(command)
|
47
|
+
return unless command =~ /<%=\s*ENV\[[\'\"]?(.+)[\'\"]\]?\s*%>/
|
48
|
+
envvar_name = Regexp.last_match(1)
|
49
|
+
if !ENV.key?(envvar_name)
|
50
|
+
@logger.error "Variable name: #{envvar_name} is not found in ENV"
|
51
|
+
elsif ENV[envvar_name] =~ /^\s*$/
|
52
|
+
@logger.warn "Env var: #{envvar_name} exists, but null string"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def embed_var(param)
|
57
|
+
check_embed_envvar(param)
|
58
|
+
erb = ERB.new(param)
|
59
|
+
erb.result(binding)
|
60
|
+
end
|
61
|
+
|
62
|
+
def embed_password
|
63
|
+
@host_param[:enable] = '_NOT_DEFINED_' unless @host_param.key?(:enable)
|
64
|
+
base_str = @enable_mode ? @host_param[:enable] : @host_param[:password]
|
65
|
+
embed_var(base_str)
|
66
|
+
end
|
67
|
+
|
68
|
+
def embed_command(command)
|
69
|
+
embed_var(command)
|
70
|
+
end
|
71
|
+
|
72
|
+
def embed_user_name
|
73
|
+
embed_var(@host_param[:username])
|
74
|
+
end
|
75
|
+
|
76
|
+
def embed_ipaddr
|
77
|
+
embed_var(@host_param[:ipaddr])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'expectacle/thrower_base'
|
4
|
+
|
5
|
+
module Expectacle
|
6
|
+
# Thrower logic(command list operation)
|
7
|
+
class Thrower < ThrowerBase
|
8
|
+
# Preview all parameters for all hosts.
|
9
|
+
# @param [Array<Hash>] hosts Host parameters (read from host list file).
|
10
|
+
# @param [Array<String>] commands Commands (read from command list file).
|
11
|
+
def preview_parameter(hosts, commands)
|
12
|
+
print YAML.dump(previewed_data(hosts, commands))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Preview all parameters for all hosts (for testing)
|
16
|
+
# @param [Array<Hash>] hosts Host parameters (read from host list file).
|
17
|
+
# @param [Array<String>] commands Commands (read from command list file).
|
18
|
+
def previewed_data(hosts, commands)
|
19
|
+
@commands = commands
|
20
|
+
hosts.map do |each|
|
21
|
+
@host_param = each
|
22
|
+
preview_command_for_host
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def preview_command_for_host
|
29
|
+
ready_to_open_host_session do |spawn_cmd|
|
30
|
+
whole_previewed_parameters(spawn_cmd)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def previewed_host_param
|
35
|
+
host_param = @host_param.dup
|
36
|
+
enable_mode = @enable_mode
|
37
|
+
@enable_mode = false
|
38
|
+
host_param[:username] = embed_user_name
|
39
|
+
host_param[:password] = embed_password
|
40
|
+
host_param[:ipaddr] = embed_ipaddr
|
41
|
+
@enable_mode = true
|
42
|
+
host_param[:enable] = embed_password
|
43
|
+
@enable_mode = enable_mode
|
44
|
+
host_param
|
45
|
+
end
|
46
|
+
|
47
|
+
def previewed_commands
|
48
|
+
@commands.map { |cmd| embed_command(cmd) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def whole_previewed_parameters(spawn_cmd)
|
52
|
+
{
|
53
|
+
spawn_cmd: spawn_cmd,
|
54
|
+
prompt: @prompt,
|
55
|
+
host: previewed_host_param,
|
56
|
+
commands: previewed_commands
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'expectacle/thrower_base_io'
|
4
|
+
|
5
|
+
module Expectacle
|
6
|
+
# Thrower logic(command list operation)
|
7
|
+
class Thrower < ThrowerBase
|
8
|
+
private
|
9
|
+
|
10
|
+
def check_auth_count
|
11
|
+
if @commands.length == @commands_len
|
12
|
+
@auth_count += 1
|
13
|
+
else
|
14
|
+
@auth_count = 0
|
15
|
+
@commands_len = @commands.length
|
16
|
+
end
|
17
|
+
return unless @auth_count > MAX_AUTH_COUNT
|
18
|
+
@logger.error "Close: Too many auth retries (#{@auth_count} times)"
|
19
|
+
@commands = []
|
20
|
+
close_session
|
21
|
+
end
|
22
|
+
|
23
|
+
def clear_auth_count
|
24
|
+
@auth_count = 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def close_session
|
28
|
+
write_and_logging 'Send break: ', 'exit'
|
29
|
+
return unless @local_serial
|
30
|
+
@logger.info 'Close IO for spawn command'
|
31
|
+
@reader.close
|
32
|
+
@writer.close
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/expectacle/version.rb
CHANGED
data/vendor/hosts/l2switch.yml
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
- :hostname : 'l2sw1'
|
2
2
|
:type : 'c3750g'
|
3
|
-
:ipaddr : '192.168.
|
4
|
-
:protocol : '
|
3
|
+
:ipaddr : '192.168.255.1'
|
4
|
+
:protocol : 'cu'
|
5
|
+
:cu_opts : '-l /dev/ttyUSB0 -s 9600'
|
5
6
|
:username : "<%= ENV['L2SW_USER'] %>"
|
6
7
|
:password : "<%= ENV['L2SW_PASS'] %>"
|
7
8
|
:enable : "<%= ENV['L2SW_PASS'] %>"
|
8
|
-
:tftp_server: '192.168.
|
9
|
+
:tftp_server: '192.168.2.16'
|
9
10
|
- :hostname : 'l2sw2'
|
10
11
|
:type : 'c3750g'
|
11
|
-
:ipaddr : '192.168.
|
12
|
+
:ipaddr : '192.168.255.2'
|
12
13
|
:protocol : 'ssh'
|
13
14
|
:username : "<%= ENV['L2SW_USER'] %>"
|
14
15
|
:password : "<%= ENV['L2SW_PASS'] %>"
|
15
16
|
:enable : "<%= ENV['L2SW_PASS'] %>"
|
16
|
-
:tftp_server: '192.168.
|
17
|
+
:tftp_server: '192.168.2.16'
|
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: expectacle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- stereocat
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -49,19 +49,25 @@ files:
|
|
49
49
|
- lib/expectacle.rb
|
50
50
|
- lib/expectacle/thrower.rb
|
51
51
|
- lib/expectacle/thrower_base.rb
|
52
|
+
- lib/expectacle/thrower_base_io.rb
|
53
|
+
- lib/expectacle/thrower_base_params.rb
|
54
|
+
- lib/expectacle/thrower_preview.rb
|
55
|
+
- lib/expectacle/thrower_utils.rb
|
52
56
|
- lib/expectacle/version.rb
|
53
57
|
- vendor/commands/cisco_save_config_tftp.yml
|
54
58
|
- vendor/commands/cisco_show_arp.yml
|
59
|
+
- vendor/commands/cisco_show_version.yml
|
55
60
|
- vendor/commands/pica8_ovs_info.yml
|
56
61
|
- vendor/commands/ssg_get_arp.yml
|
57
62
|
- vendor/commands/ssg_save_config_tftp.yml
|
58
63
|
- vendor/hosts/fw.yml
|
59
64
|
- vendor/hosts/l2switch.yml
|
60
65
|
- vendor/hosts/ofswitch.yml
|
66
|
+
- vendor/opts/cu_opts.yml
|
67
|
+
- vendor/opts/ssh_opts.yml
|
61
68
|
- vendor/prompts/c3750g_prompt.yml
|
62
69
|
- vendor/prompts/pica8_prompt.yml
|
63
70
|
- vendor/prompts/ssg_prompt.yml
|
64
|
-
- vendor/ssh_opts.yml
|
65
71
|
homepage: https://github.com/stereocat/expectacle
|
66
72
|
licenses:
|
67
73
|
- MIT
|