opswalrus 1.0.16 → 1.0.18

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: f6d990ac1fac1a918ebca3eac342377ee61702f0864e635e378ad8e69d7ec0d5
4
- data.tar.gz: 900661d04774a42b0a960624fd7fc51b9690c23ad15fba5aaf94f8a3e1241de6
3
+ metadata.gz: 27cea4b01102c518b26f6b47e47a6461ff76aac39f4ab0094955aa6413d3e9f7
4
+ data.tar.gz: ce1b064a905fea231d4d551513a74f33f726cfcfdede0e4a2660acefc17c1b62
5
5
  SHA512:
6
- metadata.gz: 88e94b27da26afb8b925f1b363c6ccf889f3e105d28e3f7d2ccfd1d2d8fe1b61d443d64dc1829c42b8644216e19bad1c4e384757246414b62dc18104421cb8fe
7
- data.tar.gz: 3e5b2b2062a592102bed054b7bae779a66b676ca8d47beb42cbab0a6cc6096e191129b3fd9a2c6fc815f8964bf78270b15687cbba99787c0323fb51c87e82c9c
6
+ metadata.gz: 5bd3daea688e85fe18e8f61bb455b238478b8be1f6caf9be2bed096af0d20187155d4882a2fb2732044eaee3f93303f1592b3025fbdfc74775a323007bd1a544
7
+ data.tar.gz: 027a8423627f1af58966e9064157c72cdfca7aec5e74f04130cd8b563ec23217ee9dc0da9ccf43afdc1b07f39bd2ab69e3d744d7355b9f27ae1536d16180caea
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- opswalrus (1.0.16)
4
+ opswalrus (1.0.18)
5
5
  amazing_print (~> 1.5)
6
6
  bcrypt_pbkdf (~> 1.1)
7
7
  citrus (~> 3.0)
@@ -9,8 +9,10 @@ PATH
9
9
  git (~> 1.18)
10
10
  gli (~> 2.21)
11
11
  ougai (~> 2.0)
12
+ pastel (~> 0.8)
12
13
  rubyzip (~> 2.3)
13
14
  sshkit (~> 1.21)
15
+ tty-editor (~> 0.7)
14
16
 
15
17
  GEM
16
18
  remote: https://rubygems.org/
@@ -32,6 +34,8 @@ GEM
32
34
  oj (3.16.0)
33
35
  ougai (2.0.0)
34
36
  oj (~> 3.10)
37
+ pastel (0.8.0)
38
+ tty-color (~> 0.5)
35
39
  public_suffix (5.0.3)
36
40
  rake (13.0.6)
37
41
  rchardet (1.8.0)
@@ -52,6 +56,19 @@ GEM
52
56
  sshkit (1.21.5)
53
57
  net-scp (>= 1.1.2)
54
58
  net-ssh (>= 2.8.0)
59
+ tty-color (0.6.0)
60
+ tty-cursor (0.7.1)
61
+ tty-editor (0.7.0)
62
+ tty-prompt (~> 0.22)
63
+ tty-prompt (0.23.1)
64
+ pastel (~> 0.8)
65
+ tty-reader (~> 0.8)
66
+ tty-reader (0.9.0)
67
+ tty-cursor (~> 0.7)
68
+ tty-screen (~> 0.8)
69
+ wisper (~> 2.0)
70
+ tty-screen (0.8.1)
71
+ wisper (2.0.1)
55
72
 
56
73
  PLATFORMS
57
74
  x86_64-linux
data/lib/opswalrus/app.rb CHANGED
@@ -1,14 +1,16 @@
1
+ require "amazing_print"
1
2
  require "citrus"
2
3
  require "io/console"
3
4
  require "json"
4
5
  # require "logger"
5
6
  require "random/formatter"
6
7
  require "ougai"
8
+ require "pastel"
9
+ require "pathname"
7
10
  require "shellwords"
8
11
  require "socket"
9
12
  require "stringio"
10
13
  require "yaml"
11
- require "pathname"
12
14
  require_relative "errors"
13
15
  require_relative "patches"
14
16
  require_relative "git"
@@ -21,6 +23,8 @@ require_relative "version"
21
23
 
22
24
 
23
25
  module OpsWalrus
26
+ Style = Pastel.new(enabled: $stdout.tty?)
27
+
24
28
  class App
25
29
  def self.instance(*args)
26
30
  @instance ||= new(*args)
@@ -32,9 +36,14 @@ module OpsWalrus
32
36
  attr_reader :local_hostname
33
37
 
34
38
  def initialize(pwd = Dir.pwd)
35
- @logger = Ougai::Logger.new($stdout, level: Logger::INFO) # Logger.new($stdout, level: Logger::INFO)
39
+ @logger = Ougai::Logger.new($stdout) # Logger.new($stdout, level: Logger::INFO)
40
+ @logger.level = :info # , :trace or 'trace'
36
41
  @logger.formatter = Ougai::Formatters::Readable.new
37
42
 
43
+ # @logger.warn Style.yellow("warn"), foo: "bar", baz: {qux: "quux"}
44
+ # @logger.info Style.yellow("info"), foo: "bar", baz: {qux: "quux"}
45
+ # @logger.debug Style.yellow("debug"), foo: "bar", baz: {qux: "quux"}
46
+ # @logger.trace Style.yellow("trace"), foo: "bar", baz: {qux: "quux"}
38
47
 
39
48
  @verbose = false
40
49
  @sudo_user = nil
@@ -46,6 +55,7 @@ module OpsWalrus
46
55
  @bundler = Bundler.new(@pwd)
47
56
  @local_hostname = "localhost"
48
57
  @mode = :report # :report | :script
58
+ @dry_run = false
49
59
  end
50
60
 
51
61
  def to_s
@@ -68,6 +78,14 @@ module OpsWalrus
68
78
  @mode == :script
69
79
  end
70
80
 
81
+ def dry_run?
82
+ @dry_run
83
+ end
84
+
85
+ def dry_run!
86
+ @dry_run = true
87
+ end
88
+
71
89
  def set_local_hostname(hostname)
72
90
  hostname = hostname.strip
73
91
  @local_hostname = hostname.empty? ? "localhost" : hostname
@@ -91,37 +109,54 @@ module OpsWalrus
91
109
  @bundler.bundle_dir
92
110
  end
93
111
 
94
- def set_verbose(verbose)
95
- @verbose = verbose
96
- @logger.debug! if verbose?
112
+ # log_level = :fatal, :error, :warn, :info, :debug, :trace
113
+ # irb(main):018:0> Ougai::Logger::TRACE
114
+ # => -1
115
+ # irb(main):019:0> Ougai::Logger::DEBUG
116
+ # => 0
117
+ # irb(main):020:0> Ougai::Logger::INFO
118
+ # => 1
119
+ # irb(main):021:0> Ougai::Logger::WARN
120
+ # => 2
121
+ # irb(main):022:0> Ougai::Logger::ERROR
122
+ # => 3
123
+ # irb(main):023:0> Ougai::Logger::FATAL
124
+ # => 4
125
+ def set_log_level(log_level)
126
+ @logger.level = log_level
97
127
  end
98
128
 
99
129
  def verbose?
100
- @verbose
130
+ @logger.level <= 1
101
131
  end
102
132
 
103
133
  def debug?
104
- @verbose == 2
134
+ @logger.level <= 0
135
+ end
136
+
137
+ def fatal(*args)
138
+ @logger.fatal(*args)
105
139
  end
106
140
 
107
- def error(msg)
108
- @logger.error(msg)
141
+ def error(*args)
142
+ @logger.error(*args)
109
143
  end
110
144
 
111
- def warn(msg)
112
- @logger.warn(msg)
145
+ def warn(*args)
146
+ @logger.warn(*args)
113
147
  end
114
148
 
115
- def log(msg)
116
- @logger.info(msg)
149
+ def log(*args)
150
+ @logger.info(*args)
117
151
  end
152
+ alias_method :info, :log
118
153
 
119
- def debug(msg)
120
- @logger.debug(msg)
154
+ def debug(*args)
155
+ @logger.debug(*args)
121
156
  end
122
157
 
123
- def trace(msg)
124
- @logger.trace(msg)
158
+ def trace(*args)
159
+ @logger.trace(*args)
125
160
  end
126
161
 
127
162
  def set_pwd(pwd)
@@ -9,6 +9,7 @@ if [ -x "$(command -v /home/linuxbrew/.linuxbrew/bin/brew)" ]; then
9
9
  echo 'Ruby is already installed.' >&2
10
10
 
11
11
  # make sure the latest opswalrus gem is installed
12
+ # todo: figure out how to install this differently, so that test versions will work
12
13
  gem install opswalrus
13
14
 
14
15
  exit 0
@@ -26,6 +26,10 @@ module OpsWalrus
26
26
  FileUtils.mkdir_p(@bundle_dir) unless @bundle_dir.exist?
27
27
  end
28
28
 
29
+ def delete_pwd_bundle_directory
30
+ FileUtils.remove_dir(@bundle_dir) if @bundle_dir.exist?
31
+ end
32
+
29
33
  # # returns the OpsFile within the bundle directory that represents the given ops_file (which is outside of the bundle directory)
30
34
  # def build_bundle_for_ops_file(ops_file)
31
35
  # if ops_file.package_file # ops_file is part of larger package
@@ -50,6 +54,7 @@ module OpsWalrus
50
54
  # end
51
55
 
52
56
  def update
57
+ delete_pwd_bundle_directory
53
58
  ensure_pwd_bundle_directory_exists
54
59
 
55
60
  package_yaml_files = pwd.glob("./**/package.yaml") - pwd.glob("./**/#{BUNDLE_DIR}/**/package.yaml")
@@ -110,36 +115,16 @@ module OpsWalrus
110
115
  version = package_reference.version
111
116
 
112
117
  destination_package_path = @bundle_dir.join(package_reference.import_resolution_dirname)
113
- FileUtils.remove_dir(destination_package_path) if destination_package_path.exist?
118
+
119
+ # we return early here under the assumption that an already downloaded package/version combo will not
120
+ # differ if we download it again multiple times to the same location
121
+ if destination_package_path.exist?
122
+ App.instance.log("Skipping #{package_reference} referenced in #{package_file.package_file_path} since it already has been downloaded to #{destination_package_path}")
123
+ return destination_package_path
124
+ end
125
+ # FileUtils.remove_dir(destination_package_path) if destination_package_path.exist?
114
126
 
115
127
  download_package_contents(package_file, local_name, package_url, version, destination_package_path)
116
- # case
117
- # when package_url =~ /\.git/ # git reference
118
- # download_git_package(package_url, version, destination_package_path)
119
- # when package_url.start_with?("file://") # local path
120
- # path = package_url.sub("file://", "")
121
- # path = path.to_pathname
122
- # package_path_to_download = if path.relative? # relative path
123
- # package_file.containing_directory.join(path)
124
- # else # absolute path
125
- # path.realpath
126
- # end
127
-
128
- # raise Error, "Package not found: #{package_path_to_download}" unless package_path_to_download.exist?
129
- # FileUtils.cp_r(package_path_to_download, destination_package_path)
130
- # when package_url.to_pathname.exist? || package_file.containing_directory.join(package_url).exist? # local path
131
- # path = package_url.to_pathname
132
- # package_path_to_download = if path.relative? # relative path
133
- # package_file.containing_directory.join(path)
134
- # else # absolute path
135
- # path.realpath
136
- # end
137
-
138
- # raise Error, "Package not found: #{package_path_to_download}" unless File.exist?(package_path_to_download)
139
- # FileUtils.cp_r(package_path_to_download, destination_package_path)
140
- # else # git reference
141
- # download_git_package(package_url, version, destination_package_path)
142
- # end
143
128
 
144
129
  destination_package_path
145
130
  end
@@ -147,10 +132,12 @@ module OpsWalrus
147
132
  def download_package_contents(package_file, local_name, package_url, version, destination_package_path)
148
133
  package_path = package_url.to_pathname
149
134
  package_path = package_path.to_s.gsub(/^~/, Dir.home).to_pathname
135
+ App.instance.trace("download_package_contents #{package_path}")
150
136
  if package_path.absolute? && package_path.exist? # absolute path reference
151
137
  return case
152
138
  when package_path.directory?
153
139
  package_path_to_download = package_path.realpath
140
+ App.instance.debug("Copying #{package_path_to_download} to #{destination_package_path}")
154
141
  FileUtils.cp_r(package_path_to_download, destination_package_path)
155
142
  when package_path.file?
156
143
  raise Error, "Package reference must be a directory, not a file:: #{local_name}: #{package_path}"
@@ -163,6 +150,7 @@ module OpsWalrus
163
150
  if rebased_path.exist?
164
151
  return case
165
152
  when rebased_path.directory?
153
+ App.instance.debug("Copying #{package_path_to_download} to #{destination_package_path}")
166
154
  package_path_to_download = rebased_path.realpath
167
155
  FileUtils.cp_r(package_path_to_download, destination_package_path)
168
156
  when rebased_path.file?
@@ -174,6 +162,7 @@ module OpsWalrus
174
162
  end
175
163
 
176
164
  if package_uri = Git.repo?(package_url) # git repo
165
+ App.instance.debug("Cloning repo #{package_uri} into #{destination_package_path}")
177
166
  download_git_package(package_uri, version, destination_package_path)
178
167
  end
179
168
  end
@@ -195,15 +184,10 @@ module OpsWalrus
195
184
  end
196
185
 
197
186
  def dynamic_package_path_for_git_package(package_url, version = nil)
198
- package_reference_dirname = sanitize_path(package_url)
187
+ package_reference_dirname = DynamicPackageReference.import_resolution_dirname(package_url, version)
199
188
  bundle_dir.join(package_reference_dirname)
200
189
  end
201
190
 
202
- def sanitize_path(path)
203
- # found this at https://apidock.com/rails/v5.2.3/ActiveStorage/Filename/sanitized
204
- path.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "�").strip.tr("\u{202E}%$|:;/\t\r\n\\", "-")
205
- end
206
-
207
191
  # returns the directory that the zip file is unzipped into
208
192
  def unzip(zip_bundle_file, output_dir = nil)
209
193
  if zip_bundle_file.to_pathname.exist?
data/lib/opswalrus/cli.rb CHANGED
@@ -9,7 +9,7 @@ module OpsWalrus
9
9
 
10
10
  pre do |global_options, command, options, args|
11
11
  $app = App.instance(Dir.pwd)
12
- $app.set_local_hostname(ENV["WALRUS_LOCAL_HOSTNAME"]) if ENV["WALRUS_LOCAL_HOSTNAME"]
12
+ $app.set_local_hostname(ENV["OPSWALRUS_LOCAL_HOSTNAME"]) if ENV["OPSWALRUS_LOCAL_HOSTNAME"]
13
13
  true
14
14
  end
15
15
 
@@ -31,6 +31,10 @@ module OpsWalrus
31
31
  desc 'Turn on debug mode'
32
32
  switch [:d, :debug]
33
33
 
34
+ switch :noop, desc: "Perform a dry run"
35
+ switch :dryrun, desc: "Perform a dry run"
36
+ switch :dry_run, desc: "Perform a dry run"
37
+
34
38
  flag [:h, :hosts], multiple: true, desc: "Specify the hosts.yaml file"
35
39
  flag [:t, :tags], multiple: true, desc: "Specify a set of tags to filter the hosts by"
36
40
 
@@ -48,7 +52,8 @@ module OpsWalrus
48
52
  hosts = global_options[:hosts]
49
53
  tags = global_options[:tags]
50
54
 
51
- $app.set_verbose(global_options[:debug] || global_options[:verbose])
55
+ log_level = global_options[:debug] && :trace || global_options[:verbose] && :debug || :info
56
+ $app.set_log_level(log_level)
52
57
 
53
58
  $app.report_inventory(hosts, tags: tags)
54
59
  end
@@ -63,28 +68,31 @@ module OpsWalrus
63
68
  c.flag [:p, :params], desc: "JSON string that represents the input parameters for the operation. The JSON string must conform to the params schema for the operation."
64
69
  c.switch :script, desc: "Script mode"
65
70
 
71
+ # dry run
72
+ c.switch :noop, desc: "Perform a dry run"
73
+ c.switch :dryrun, desc: "Perform a dry run"
74
+ c.switch :dry_run, desc: "Perform a dry run"
75
+
66
76
  c.action do |global_options, options, args|
77
+ log_level = global_options[:debug] && :trace || global_options[:verbose] && :debug || :info
78
+ $app.set_log_level(log_level)
79
+
67
80
  hosts = global_options[:hosts] || []
68
81
  tags = global_options[:tags] || []
69
82
 
70
83
  $app.set_inventory_hosts(hosts)
71
84
  $app.set_inventory_tags(tags)
72
85
 
73
- verbose = case
74
- when global_options[:debug]
75
- 2
76
- when global_options[:verbose]
77
- 1
78
- end
79
-
80
86
  user = options[:user]
81
87
  params = options[:params]
82
88
 
83
- $app.set_verbose(verbose)
84
89
  $app.set_params(params)
85
90
 
86
91
  $app.set_sudo_user(user) if user
87
92
 
93
+ dry_run = [:noop, :dryrun, :dry_run].any? {|sym| global_options[sym] || options[sym] }
94
+ $app.dry_run! if dry_run
95
+
88
96
  if options[:pass]
89
97
  $app.prompt_sudo_password
90
98
  end
@@ -107,6 +115,9 @@ module OpsWalrus
107
115
  long_desc 'Download and bundle the latest versions of dependencies for the current package'
108
116
  c.command :update do |update|
109
117
  update.action do |global_options, options, args|
118
+ log_level = global_options[:debug] && :trace || global_options[:verbose] && :debug || :info
119
+ $app.set_log_level(log_level)
120
+
110
121
  $app.bundle_update
111
122
  end
112
123
  end
@@ -125,6 +136,9 @@ module OpsWalrus
125
136
  unzip.flag [:o, :output], desc: "Specify the output directory"
126
137
 
127
138
  unzip.action do |global_options, options, args|
139
+ log_level = global_options[:debug] && :trace || global_options[:verbose] && :debug || :info
140
+ $app.set_log_level(log_level)
141
+
128
142
  output_dir = options[:output]
129
143
  zip_file_path = args.first
130
144
 
@@ -18,20 +18,20 @@ module OpsWalrus
18
18
  ops_file.local_symbol_table.each do |symbol_name, import_reference|
19
19
  unless methods_defined.include? symbol_name
20
20
  klass.define_method(symbol_name) do |*args, **kwargs, &block|
21
- # puts "resolving local symbol table entry: #{symbol_name}"
21
+ App.instance.trace "resolving local symbol table entry: #{symbol_name}"
22
22
  namespace_or_ops_file = @runtime_env.resolve_import_reference(ops_file, import_reference)
23
- # puts "namespace_or_ops_file=#{namespace_or_ops_file.to_s}"
23
+ App.instance.trace "namespace_or_ops_file=#{namespace_or_ops_file.to_s}"
24
24
 
25
25
  invocation_context = case import_reference
26
26
  # we know we're dealing with a package dependency reference, so we want to run an ops file contained within the bundle directory,
27
27
  # therefore, we want to reference the specified ops file with respect to the bundle dir
28
28
  when PackageDependencyReference
29
- RemoteImportInvocationContext.new(@runtime_env, self, namespace_or_ops_file, true)
29
+ RemoteImportInvocationContext.new(@runtime_env, self, namespace_or_ops_file, true, prompt_for_sudo_password: !!ssh_password)
30
30
 
31
31
  # we know we're dealing with a directory reference or OpsFile reference outside of the bundle dir, so we want to reference
32
32
  # the specified ops file with respect to the root directory, and not with respect to the bundle dir
33
33
  when DirectoryReference, OpsFileReference
34
- RemoteImportInvocationContext.new(@runtime_env, self, namespace_or_ops_file, false)
34
+ RemoteImportInvocationContext.new(@runtime_env, self, namespace_or_ops_file, false, prompt_for_sudo_password: !!ssh_password)
35
35
  end
36
36
 
37
37
  invocation_context._invoke(*args, **kwargs)
@@ -49,7 +49,11 @@ module OpsWalrus
49
49
  unless methods_defined.include? symbol_name
50
50
  # puts "2. defining: #{symbol_name}(...)"
51
51
  klass.define_method(symbol_name) do |*args, **kwargs, &block|
52
- invocation_context = RemoteImportInvocationContext.new(@runtime_env, self, namespace_or_ops_file, false)
52
+ App.instance.trace "resolving implicit import: #{symbol_name}"
53
+ namespace_or_ops_file = @runtime_env.resolve_sibling_symbol(ops_file, symbol_name)
54
+ App.instance.trace "namespace_or_ops_file=#{namespace_or_ops_file.to_s}"
55
+
56
+ invocation_context = RemoteImportInvocationContext.new(@runtime_env, self, namespace_or_ops_file, false, prompt_for_sudo_password: !!ssh_password)
53
57
  invocation_context._invoke(*args, **kwargs)
54
58
  end
55
59
  methods_defined << symbol_name
@@ -107,13 +111,14 @@ module OpsWalrus
107
111
  #cmd = Shellwords.escape(cmd)
108
112
 
109
113
  if App.instance.report_mode?
114
+ puts Style.green("*" * 80)
110
115
  if self.alias
111
- print "[#{self.alias} | #{host}] "
116
+ print "[#{Style.blue(self.alias)} | #{Style.blue(host)}] "
112
117
  else
113
- print "[#{host}] "
118
+ print "[#{Style.blue(host)}] "
114
119
  end
115
120
  print "#{description}: " if description
116
- puts cmd
121
+ puts Style.yellow(cmd)
117
122
  end
118
123
 
119
124
  return unless cmd && !cmd.strip.empty?
@@ -122,9 +127,12 @@ module OpsWalrus
122
127
  # puts "shell: #{cmd.inspect}"
123
128
  # puts "sudo_password: #{sudo_password}"
124
129
 
125
- sshkit_cmd = execute_cmd(cmd, input: input)
126
-
127
- [sshkit_cmd.full_stdout, sshkit_cmd.full_stderr, sshkit_cmd.exit_status]
130
+ if App.instance.dry_run?
131
+ ["", "", 0]
132
+ else
133
+ sshkit_cmd = execute_cmd(cmd, input: input)
134
+ [sshkit_cmd.full_stdout, sshkit_cmd.full_stderr, sshkit_cmd.exit_status]
135
+ end
128
136
  end
129
137
 
130
138
  # def init_brew
@@ -137,7 +145,13 @@ module OpsWalrus
137
145
  # e.g. /home/linuxbrew/.linuxbrew/bin/gem exec -g opswalrus ops run echo.ops args:foo args:bar
138
146
 
139
147
  # cmd = "/home/linuxbrew/.linuxbrew/bin/gem exec -g opswalrus ops"
140
- cmd = "/home/linuxbrew/.linuxbrew/bin/gem exec -g opswalrus ops"
148
+ local_hostname_for_remote_host = if self.alias
149
+ "#{self.alias} | #{host}"
150
+ else
151
+ host
152
+ end
153
+
154
+ cmd = "OPSWALRUS_LOCAL_HOSTNAME='#{local_hostname_for_remote_host}'; /home/linuxbrew/.linuxbrew/bin/gem exec -g opswalrus ops"
141
155
  cmd << " -v" if verbose
142
156
  cmd << " #{ops_command.to_s}"
143
157
  cmd << " #{ops_command_options.to_s}" if ops_command_options
@@ -5,6 +5,7 @@ module OpsWalrus
5
5
  class ScopedMappingInteractionHandler
6
6
  attr_accessor :input_mappings # Hash[ String | Regex => String ]
7
7
 
8
+ # log_level is one of: :fatal, :error, :warn, :info, :debug, :trace
8
9
  def initialize(mapping, log_level = nil)
9
10
  @log_level = log_level
10
11
  @input_mappings = mapping
@@ -21,11 +22,10 @@ module OpsWalrus
21
22
  # end
22
23
 
23
24
  # sudo_password : String
24
- def mapping_for_sudo_password(sudo_password)
25
+ def self.mapping_for_sudo_password(sudo_password)
25
26
  {
26
27
  /\[sudo\] password for .*?:\s*/ => "#{sudo_password}\n",
27
28
  App::LOCAL_SUDO_PASSWORD_PROMPT => "#{sudo_password}\n",
28
- # /\s+/ => nil, # unnecessary
29
29
  }
30
30
  end
31
31
 
@@ -39,7 +39,7 @@ module OpsWalrus
39
39
  raise ArgumentError.new("mapping must be a Hash") unless mapping.is_a?(Hash)
40
40
 
41
41
  if sudo_password
42
- mapping.merge!(mapping_for_sudo_password(sudo_password))
42
+ mapping.merge!(ScopedMappingInteractionHandler.mapping_for_sudo_password(sudo_password))
43
43
  end
44
44
 
45
45
  if mapping.empty?
@@ -57,17 +57,16 @@ module OpsWalrus
57
57
  end
58
58
 
59
59
  def on_data(_command, stream_name, data, channel)
60
- log("Looking up response for #{stream_name} message #{data.inspect}")
61
-
62
60
  response_data = begin
63
61
  first_matching_key_value_pair = @input_mappings.find {|k, _v| k === data }
64
62
  first_matching_key_value_pair&.last
65
63
  end
66
64
 
67
65
  if response_data.nil?
68
- log("Unable to find interaction handler mapping for #{stream_name}: #{data.inspect} so no response was sent")
66
+ trace(Style.red("No interaction handler mapping for #{stream_name}: #{data} so no response was sent"))
69
67
  else
70
- log("Sending #{response_data.inspect}")
68
+ debug(Style.cyan("Handling #{stream_name} message #{data}"))
69
+ debug(Style.cyan("Sending response #{response_data}"))
71
70
  if channel.respond_to?(:send_data) # Net SSH Channel
72
71
  channel.send_data(response_data)
73
72
  elsif channel.respond_to?(:write) # Local IO
@@ -80,16 +79,21 @@ module OpsWalrus
80
79
 
81
80
  private
82
81
 
83
- def log(message)
84
- # puts message
85
- SSHKit.config.output.send(@log_level, message) unless @log_level.nil?
82
+ def trace(message)
83
+ App.instance.trace(message)
84
+ end
85
+
86
+ def debug(message)
87
+ App.instance.debug(message)
88
+ if [:fatal, :error, :warn, :info, :debug, :trace].include? @log_level
89
+ SSHKit.config.output.send(@log_level, message)
90
+ end
86
91
  end
87
92
 
88
93
  end
89
94
 
90
95
  class PasswdInteractionHandler
91
96
  def on_data(command, stream_name, data, channel)
92
- # puts data
93
97
  case data
94
98
  when '(current) UNIX password: '
95
99
  channel.send_data("old_pw\n")
@@ -118,8 +122,6 @@ module OpsWalrus
118
122
 
119
123
  class SudoPromptInteractionHandler
120
124
  def on_data(command, stream_name, data, channel)
121
- # puts "0" * 80
122
- # puts data.inspect
123
125
  case data
124
126
  when /\[sudo\] password for/
125
127
  if channel.respond_to?(:send_data) # Net::SSH channel
@@ -128,12 +130,11 @@ module OpsWalrus
128
130
  channel.write("conquer\n")
129
131
  end
130
132
  when /\s+/
131
- puts 'space, do nothing'
133
+ nil
132
134
  else
133
135
  raise "Unexpected prompt: #{data} on stream #{stream_name} and channel #{channel.inspect}"
134
- end
136
+ end
135
137
  end
136
138
  end
137
139
 
138
-
139
140
  end