expectacle 0.0.1 → 0.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d1decbec1db35ee28a8b21210f8f61c42cff269
4
- data.tar.gz: 33563494544b430040b0c1488280f48474a48062
3
+ metadata.gz: 70d0dd97af8fb79becf1a01a31b11fc81ddc3c64
4
+ data.tar.gz: 20bf4dd2c8fca9af93f07bbf90b011481169b88b
5
5
  SHA512:
6
- metadata.gz: fc8348cd4cf0fecc78dc5b72ad45169d144d01d1a5c467236cf661e3492c0a2782579b4e97be562ea4fe4a8db7dabfef314c47d65a14556f5635f1c686ddd4b7
7
- data.tar.gz: e870762f009586844c50b4ea06e5a7bed8179a94d06800542a602599d90b80bf6e1a4e9f3ad4966797f61b241459dbfc29ac58941f8aa52cffbe1e2a327aeb8d
6
+ metadata.gz: d2bb97f3b5bce0bcdf449b1ab9350cd403099e6d5e2de11356b05159ec872fcff2681142311e00830ceffb44b91ec59a396787f06728022cf3744fd906860e56
7
+ data.tar.gz: 94941d88e8c6ab26e3c940fd3af4ef5ecd112b710ebe117103f040f14d5476ccdd412520124d964a1aca1e2d7dbbda5c88ab88213b970875546ec5203140cf25
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup-provider=redcarpet
2
+ --markup=markdown
data/Gemfile CHANGED
@@ -9,4 +9,10 @@ group :test do
9
9
  gem 'simplecov'
10
10
  end
11
11
 
12
+ group :development do
13
+ gem 'yard'
14
+ gem 'redcarpet'
15
+ gem 'github-markup'
16
+ end
17
+
12
18
  gem 'rubocop'
data/README.md CHANGED
@@ -55,6 +55,55 @@ Input: (type password)
55
55
  - it is a list of commands.
56
56
  - Each files are written by YAML.
57
57
 
58
+ ### Parameter expansion and preview
59
+ Expectacle has parameter expansion feature using ERB.
60
+ In a command list file,
61
+ you can write command strings including environment variable and parameters defined in host file.
62
+ See [Parameter definitions](#parameter-definitions) section about details of parameter expansion feature.
63
+
64
+ Thereby, there are some risks sending danger commands by using wrong parameter and command definitions.
65
+
66
+ Then, you can preview expanded command strings to send a host and parameters before execute actually.
67
+ For Example:
68
+ ```
69
+ stereocat@tftpserver:~/expectacle$ bundle exec run_command -p -h l2switch.yml -c cisco_save_config_tftp.yml
70
+ ---
71
+ :spawn_cmd: ssh -o StrictHostKeyChecking=no -o KexAlgorithms=+diffie-hellman-group1-sha1
72
+ -l cisco 192.168.20.150
73
+ :prompt:
74
+ :password: "^Password\\s*:"
75
+ :username: "^Username\\s*:"
76
+ :sub1: "\\][:\\?]"
77
+ :sub2: "\\[confirm\\]"
78
+ :yn: "\\[yes\\/no\\]:"
79
+ :command1: "^[\\w\\-]+>"
80
+ :command2: "^[\\w\\-]+(:?\\(config\\))?\\#"
81
+ :enable_password: SAME_AS_LOGIN_PASSWORD
82
+ :enable_command: enable
83
+ :host:
84
+ :hostname: l2sw1
85
+ :type: c3750g
86
+ :ipaddr: 192.168.20.150
87
+ :protocol: ssh
88
+ :username: cisco
89
+ :password: ********
90
+ :enable: ********
91
+ :tftp_server: 192.168.20.170
92
+ :commands:
93
+ - copy run start
94
+ - copy run tftp://192.168.20.170/l2sw1.confg
95
+ ---
96
+ (snip)
97
+ ```
98
+ **Notice** : Passwords were masked above example, but actually, raw password string are printed out.
99
+
100
+ ### Use Syslog
101
+
102
+ With `-s`/`--syslog`, [run_command](./exe/run_command) changes logging instance to `syslog/logger`.
103
+ So, log messages are printed out to syslog on localhost.
104
+
105
+ $ bundle exec run_command -rs -h l2switch.yml -c cisco_show_arp.yml
106
+
58
107
  ## Parameter Definitions
59
108
 
60
109
  ### Expectacle::Thrower
@@ -147,7 +196,7 @@ Feature for sub-prompt (interactive command) is not enough.
147
196
  Now, Expectacle sends fixed command for sub-prompt.
148
197
  (These actions were defined for cisco to execute above "copy run" example...)
149
198
  - Yex/No (`:yn`) : always sends "yes"
150
- - Sub prompt (`:sub1` and `:sub2`) : Empty string (RETURN)
199
+ - Sub prompt (`:sub1` and `:sub2`) : always sends Empty string (RETURN)
151
200
 
152
201
  ## Contributing
153
202
 
data/Rakefile CHANGED
@@ -18,3 +18,15 @@ rescue LoadError
18
18
  $stderr.puts 'RuboCop is disabled'
19
19
  end
20
20
  end
21
+
22
+ begin
23
+ require 'yard'
24
+ require 'yard/rake/yardoc_task'
25
+ YARD::Rake::YardocTask.new do |task|
26
+ task.files = FileList['./lib/**/*.rb']
27
+ end
28
+ rescue LoadError
29
+ task :yard do
30
+ $stderr.puts 'YARD is disabled'
31
+ end
32
+ end
data/exe/run_command CHANGED
@@ -4,6 +4,7 @@
4
4
  require 'expectacle'
5
5
  require 'optparse'
6
6
  require 'yaml'
7
+ require 'syslog/logger'
7
8
 
8
9
  option = {}
9
10
  opt = OptionParser.new
@@ -22,16 +23,24 @@ end
22
23
  opt.on('-r', '--run', 'Run(exec) commands to each hosts') do |value|
23
24
  option[:run] = value
24
25
  end
26
+ opt.on('-s', '--syslog', 'Use syslog logger (use localhost syslog)') do |value|
27
+ option[:syslog] = value
28
+ end
25
29
  opt.parse!(ARGV)
26
30
 
27
- file_dir = File.dirname(File.expand_path(__FILE__))
28
31
  base_dir = if option.key?(:base_dir)
29
32
  option[:base_dir]
30
33
  else
34
+ file_dir = File.dirname(File.expand_path(__FILE__))
31
35
  File.expand_path('../vendor', file_dir)
32
36
  end
33
37
  thrower = Expectacle::Thrower.new(base_dir: base_dir)
34
38
 
39
+ if option[:syslog]
40
+ thrower.logger = Syslog::Logger.new 'Expectacle'
41
+ thrower.setup_logger
42
+ end
43
+
35
44
  hosts = YAML.load_file(File.join(thrower.hosts_dir, option[:hosts]))
36
45
  commands = YAML.load_file(File.join(thrower.commands_dir, option[:commands]))
37
46
  if option[:preview]
@@ -5,14 +5,20 @@ require 'expectacle/thrower_base'
5
5
  module Expectacle
6
6
  # Thrower logic(command list operation)
7
7
  class Thrower < ThrowerBase
8
+ # Run(exec) commands 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).
8
11
  def run_command_for_all_hosts(hosts, commands)
9
- @commands = commands
10
12
  hosts.each do |each|
13
+ @commands = commands.dup # Notice: @commands will be decremented.
11
14
  @host_param = each
12
15
  run_command_for_host
13
16
  end
14
17
  end
15
18
 
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).
16
22
  def preview_parameter(hosts, commands)
17
23
  @commands = commands
18
24
  hosts.each do |each|
@@ -33,7 +39,7 @@ module Expectacle
33
39
 
34
40
  def preview_command_for_host
35
41
  ready_to_open_host_session do |spawn_cmd|
36
- preview_command spawn_cmd
42
+ print YAML.dump(whole_previewed_parameters(spawn_cmd))
37
43
  end
38
44
  end
39
45
 
@@ -44,29 +50,29 @@ module Expectacle
44
50
  end
45
51
  end
46
52
 
47
- def preview_host_param
53
+ def previewed_host_param
48
54
  host_param = @host_param.dup
49
55
  enable_mode = @enable_mode
50
56
  @enable_mode = false
51
- host_param[:username] = embed_user_name(binding)
52
- host_param[:password] = embed_password(binding)
57
+ host_param[:username] = embed_user_name
58
+ host_param[:password] = embed_password
53
59
  @enable_mode = true
54
- host_param[:enable] = embed_password(binding)
60
+ host_param[:enable] = embed_password
55
61
  @enable_mode = enable_mode
56
62
  host_param
57
63
  end
58
64
 
59
- def preview_commands
60
- @commands.map { |cmd| embed_command(cmd, binding) }
65
+ def previewed_commands
66
+ @commands.map { |cmd| embed_command(cmd) }
61
67
  end
62
68
 
63
- def preview_command(spawn_cmd)
64
- data = {}
65
- data[:spawn_cmd] = spawn_cmd
66
- data[:prompt] = @prompt
67
- data[:host] = preview_host_param
68
- data[:commands] = preview_commands
69
- print YAML.dump(data)
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
+ }
70
76
  end
71
77
 
72
78
  def exec_rest_commands
@@ -81,7 +87,7 @@ module Expectacle
81
87
  exec_rest_commands do
82
88
  # Notice: @commands changed
83
89
  command = @commands.shift
84
- write_and_logging 'Send command: ', embed_command(command, binding)
90
+ write_and_logging 'Send command: ', embed_command(command)
85
91
  end
86
92
  end
87
93
 
@@ -114,9 +120,9 @@ module Expectacle
114
120
  def exec_each_prompt(prompt)
115
121
  case prompt
116
122
  when /#{@prompt[:password]}/, /#{@prompt[:enable_password]}/
117
- write_and_logging 'Send password', embed_password(binding), true
123
+ write_and_logging 'Send password', embed_password, true
118
124
  when /#{@prompt[:username]}/
119
- write_and_logging 'Send username: ', embed_user_name(binding)
125
+ write_and_logging 'Send username: ', embed_user_name
120
126
  when /#{@prompt[:command2]}/, /#{@prompt[:command1]}/
121
127
  exec_by_mode(prompt)
122
128
  when /#{@prompt[:yn]}/, /#{@prompt[:sub1]}/, /#{@prompt[:sub2]}/
@@ -9,11 +9,23 @@ require 'logger'
9
9
  module Expectacle
10
10
  # Basic state setup/management
11
11
  class ThrowerBase
12
+ # @return [Logger] Logger instance.
12
13
  attr_accessor :logger
14
+ # @return [String] Base directory path to find params/hosts/commands file.
13
15
  attr_reader :base_dir
14
16
 
17
+ # Constructor
18
+ # @param timeout [Integer] Seconds to timeout. (default: 60sec)
19
+ # @param verbose [Boolean] Flag to enable verbose output.
20
+ # (default: `true`)
21
+ # @param base_dir [String] Base directory to find files.
22
+ # (default: `Dir.pwd`)
23
+ # @param logger [IO] IO Object to logging. (default `$stdout`)
24
+ # @return [Expectacle::ThrowerBase]
15
25
  def initialize(timeout: 60, verbose: true,
16
26
  base_dir: Dir.pwd, logger: $stdout)
27
+ # default
28
+ @host_param = {}
17
29
  # remote connection timeout (sec)
18
30
  @timeout = timeout
19
31
  # cli mode flag
@@ -23,23 +35,44 @@ module Expectacle
23
35
  # base dir
24
36
  @base_dir = File.expand_path(base_dir)
25
37
  # logger
26
- setup_default_logger(logger)
38
+ @logger = Logger.new(logger)
39
+ setup_default_logger
27
40
  end
28
41
 
42
+ # Path to prompt file directory.
43
+ # @return [String]
29
44
  def prompts_dir
30
45
  File.join @base_dir, 'prompts'
31
46
  end
32
47
 
48
+ # Path to host list file directory.
49
+ # @return [String]
33
50
  def hosts_dir
34
51
  File.join @base_dir, 'hosts'
35
52
  end
36
53
 
54
+ # Path to command list file directory.
55
+ # @return [String]
37
56
  def commands_dir
38
57
  File.join @base_dir, 'commands'
39
58
  end
40
59
 
60
+ # Setup common settings of logger instance.
61
+ def setup_logger
62
+ @logger.level = Logger::INFO
63
+ @logger.formatter = proc do |severity, datetime, progname, msg|
64
+ "#{datetime} #{progname} [#{severity}] #{msg}\n"
65
+ end
66
+ end
67
+
41
68
  private
42
69
 
70
+ def setup_default_logger
71
+ @logger.progname = 'Expectacle'
72
+ @logger.datetime_format = '%Y-%m-%d %H:%M:%D %Z'
73
+ setup_logger
74
+ end
75
+
43
76
  def ready_to_open_host_session
44
77
  # prompt regexp of device
45
78
  load_prompt_file
@@ -78,7 +111,7 @@ module Expectacle
78
111
  ['ssh',
79
112
  '-o StrictHostKeyChecking=no',
80
113
  '-o KexAlgorithms=+diffie-hellman-group1-sha1', # for old cisco device
81
- "-l #{embed_user_name(binding)}",
114
+ "-l #{embed_user_name}",
82
115
  @host_param[:ipaddr]].join(' ')
83
116
  end
84
117
 
@@ -106,16 +139,6 @@ module Expectacle
106
139
  @prompt = load_yaml_file('prompt file', prompt_file)
107
140
  end
108
141
 
109
- def setup_default_logger(logger_io)
110
- @logger = Logger.new(logger_io)
111
- @logger.level = Logger::INFO
112
- @logger.progname = 'Expectacle'
113
- @logger.datetime_format = '%Y-%m-%d %H:%M:%D %Z'
114
- @logger.formatter = proc do |severity, datetime, progname, msg|
115
- "#{datetime} #{progname} [#{severity}] #{msg}\n"
116
- end
117
- end
118
-
119
142
  def expect_regexp
120
143
  /
121
144
  ( #{@prompt[:password]} | #{@prompt[:enable_password]}
@@ -143,7 +166,7 @@ module Expectacle
143
166
  end
144
167
  end
145
168
 
146
- def embed_password(binding)
169
+ def embed_password
147
170
  @host_param[:enable] = '_NOT_DEFINED_' unless @host_param.key?(:enable)
148
171
  base_str = @enable_mode ? @host_param[:enable] : @host_param[:password]
149
172
  check_embed_envvar(base_str)
@@ -151,12 +174,12 @@ module Expectacle
151
174
  passwd_erb.result(binding)
152
175
  end
153
176
 
154
- def embed_command(command, binding)
177
+ def embed_command(command)
155
178
  command_erb = ERB.new(command)
156
179
  command_erb.result(binding)
157
180
  end
158
181
 
159
- def embed_user_name(binding)
182
+ def embed_user_name
160
183
  check_embed_envvar(@host_param[:username])
161
184
  uname_erb = ERB.new(@host_param[:username])
162
185
  uname_erb.result(binding)
@@ -1,3 +1,4 @@
1
1
  module Expectacle
2
- VERSION = '0.0.1'.freeze
2
+ # Gem version
3
+ VERSION = '0.0.2'.freeze
3
4
  end
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.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - stereocat
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-10-28 00:00:00.000000000 Z
11
+ date: 2016-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -37,6 +37,7 @@ files:
37
37
  - ".rspec"
38
38
  - ".rubocop.yml"
39
39
  - ".rubocop_todo.yml"
40
+ - ".yardopts"
40
41
  - Gemfile
41
42
  - LICENSE.txt
42
43
  - README.md