opswalrus 1.0.15 → 1.0.17

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: 89bf0215bfa03656ade838eeecc4e8a9026c71290d65499d7df9ef9f93e482ec
4
- data.tar.gz: b434b04092d90139ce02b0f55b3c54f7027cc84d0190ed68d9d9baacf04d4c62
3
+ metadata.gz: f2ce759171a0342644a1e3e2c94555299b093095b1684a69e11142fe29292da4
4
+ data.tar.gz: 75f4cab88e00038c73df02d69718b5cd067f3ed69150c192335894128ef912d0
5
5
  SHA512:
6
- metadata.gz: c2e19399736ff4e3f46a391484342c8411cfc4c29727f0104e3a5cd46313fd68da036ca41927036351cd9d74b9d3f7f7c50dcb61cc559174e40d8e0bd4c86c64
7
- data.tar.gz: 4bddab84402b4a89d80bdda60df5eeab729d3b22a0b99f28fa4730c5ab7de051acba633b36848a7cd63648c0aea6230ffb86d97db81f67c6349282142ccf7844
6
+ metadata.gz: 6d47f83ae4dde1c9007f0d4591da7d6d9501218b15dfed542bdf9eda8538cfca14e22baa0d0a9e7dd244ef0db3fc683f862f296e296f713f500a3b084de02dac
7
+ data.tar.gz: 96877f5975e10dd6415194f5f130f3b7b31fcee66199c354cee93386116b4c0e918749c4158ec6da4a9fe64d9414410032c47d5c78c41caf2a36683cab259a03
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- opswalrus (1.0.15)
4
+ opswalrus (1.0.17)
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,15 @@
1
1
  require "citrus"
2
2
  require "io/console"
3
3
  require "json"
4
- require "logger"
4
+ # require "logger"
5
5
  require "random/formatter"
6
6
  require "ougai"
7
+ require "pastel"
8
+ require "pathname"
7
9
  require "shellwords"
8
10
  require "socket"
9
11
  require "stringio"
10
12
  require "yaml"
11
- require "pathname"
12
13
  require_relative "errors"
13
14
  require_relative "patches"
14
15
  require_relative "git"
@@ -21,6 +22,8 @@ require_relative "version"
21
22
 
22
23
 
23
24
  module OpsWalrus
25
+ Style = Pastel.new(enabled: $stdout.tty?)
26
+
24
27
  class App
25
28
  def self.instance(*args)
26
29
  @instance ||= new(*args)
@@ -32,9 +35,14 @@ module OpsWalrus
32
35
  attr_reader :local_hostname
33
36
 
34
37
  def initialize(pwd = Dir.pwd)
35
- @logger = Ougai::Logger.new($stdout, level: Logger::INFO) # Logger.new($stdout, level: Logger::INFO)
38
+ @logger = Ougai::Logger.new($stdout) # Logger.new($stdout, level: Logger::INFO)
39
+ @logger.level = :info # , :trace or 'trace'
36
40
  @logger.formatter = Ougai::Formatters::Readable.new
37
41
 
42
+ # @logger.warn Style.yellow("warn"), foo: "bar", baz: {qux: "quux"}
43
+ # @logger.info Style.yellow("info"), foo: "bar", baz: {qux: "quux"}
44
+ # @logger.debug Style.yellow("debug"), foo: "bar", baz: {qux: "quux"}
45
+ # @logger.trace Style.yellow("trace"), foo: "bar", baz: {qux: "quux"}
38
46
 
39
47
  @verbose = false
40
48
  @sudo_user = nil
@@ -46,6 +54,7 @@ module OpsWalrus
46
54
  @bundler = Bundler.new(@pwd)
47
55
  @local_hostname = "localhost"
48
56
  @mode = :report # :report | :script
57
+ @dry_run = false
49
58
  end
50
59
 
51
60
  def to_s
@@ -68,6 +77,14 @@ module OpsWalrus
68
77
  @mode == :script
69
78
  end
70
79
 
80
+ def dry_run?
81
+ @dry_run
82
+ end
83
+
84
+ def dry_run!
85
+ @dry_run = true
86
+ end
87
+
71
88
  def set_local_hostname(hostname)
72
89
  hostname = hostname.strip
73
90
  @local_hostname = hostname.empty? ? "localhost" : hostname
@@ -91,37 +108,54 @@ module OpsWalrus
91
108
  @bundler.bundle_dir
92
109
  end
93
110
 
94
- def set_verbose(verbose)
95
- @verbose = verbose
96
- @logger.debug! if verbose?
111
+ # log_level = :fatal, :error, :warn, :info, :debug, :trace
112
+ # irb(main):018:0> Ougai::Logger::TRACE
113
+ # => -1
114
+ # irb(main):019:0> Ougai::Logger::DEBUG
115
+ # => 0
116
+ # irb(main):020:0> Ougai::Logger::INFO
117
+ # => 1
118
+ # irb(main):021:0> Ougai::Logger::WARN
119
+ # => 2
120
+ # irb(main):022:0> Ougai::Logger::ERROR
121
+ # => 3
122
+ # irb(main):023:0> Ougai::Logger::FATAL
123
+ # => 4
124
+ def set_log_level(log_level)
125
+ @logger.level = log_level
97
126
  end
98
127
 
99
128
  def verbose?
100
- @verbose
129
+ @logger.level <= 1
101
130
  end
102
131
 
103
132
  def debug?
104
- @verbose == 2
133
+ @logger.level <= 0
134
+ end
135
+
136
+ def fatal(*args)
137
+ @logger.fatal(*args)
105
138
  end
106
139
 
107
- def error(msg)
108
- @logger.error(msg)
140
+ def error(*args)
141
+ @logger.error(*args)
109
142
  end
110
143
 
111
- def warn(msg)
112
- @logger.warn(msg)
144
+ def warn(*args)
145
+ @logger.warn(*args)
113
146
  end
114
147
 
115
- def log(msg)
116
- @logger.info(msg)
148
+ def log(*args)
149
+ @logger.info(*args)
117
150
  end
151
+ alias_method :info, :log
118
152
 
119
- def debug(msg)
120
- @logger.debug(msg)
153
+ def debug(*args)
154
+ @logger.debug(*args)
121
155
  end
122
156
 
123
- def trace(msg)
124
- @logger.trace(msg)
157
+ def trace(*args)
158
+ @logger.trace(*args)
125
159
  end
126
160
 
127
161
  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
 
@@ -6,94 +6,8 @@ require_relative "invocation"
6
6
 
7
7
  module OpsWalrus
8
8
 
9
- class HostProxyOpsFileInvocationBuilder
10
- def initialize(host_proxy, is_invocation_a_call_to_package_in_bundle_dir = false)
11
- @host_proxy = host_proxy
12
- @is_invocation_a_call_to_package_in_bundle_dir = is_invocation_a_call_to_package_in_bundle_dir
13
- @method_chain = []
14
- end
15
-
16
- def method_missing(method_name, *args, **kwargs)
17
- @method_chain << method_name.to_s
18
-
19
- if args.empty? && kwargs.empty? # when there are no args and no kwargs, we are just drilling down through another namespace
20
- self
21
- else
22
- # when there are args or kwargs, then the method invocation represents an attempt to run an OpsFile on a remote host,
23
- # so we want to build up a command and send it to the remote host via HostDSL#run_ops
24
- @method_chain.unshift(Bundler::BUNDLE_DIR) if @is_invocation_a_call_to_package_in_bundle_dir
25
-
26
- remote_run_command_args = @method_chain.join(" ")
27
-
28
- unless args.empty?
29
- remote_run_command_args << " "
30
- remote_run_command_args << args.join(" ")
31
- end
32
-
33
- unless kwargs.empty?
34
- remote_run_command_args << " "
35
- remote_run_command_args << kwargs.map do |k, v|
36
- case v
37
- when Array
38
- v.map {|v_element| "#{k}:#{v_element}" }
39
- else
40
- "#{k}:#{v}"
41
- end
42
- end.join(" ")
43
- end
44
-
45
- @host_proxy.run_ops(:run, "--script", remote_run_command_args)
46
- end
47
- end
48
- end
49
-
50
9
  # the subclasses of HostProxy will define methods that handle method dispatch via HostProxyOpsFileInvocationBuilder objects
51
10
  class HostProxy
52
- # def self.define_host_proxy_class(ops_file)
53
- # klass = Class.new(HostProxy)
54
-
55
- # methods_defined = Set.new
56
-
57
- # # define methods for every import in the script
58
- # ops_file.local_symbol_table.each do |symbol_name, import_reference|
59
- # unless methods_defined.include? symbol_name
60
- # # puts "1. defining: #{symbol_name}(...)"
61
- # klass.define_method(symbol_name) do |*args, **kwargs, &block|
62
- # invocation_builder = case import_reference
63
- # # we know we're dealing with a package dependency reference, so we want to run an ops file contained within the bundle directory,
64
- # # therefore, we want to reference the specified ops file with respect to the bundle dir
65
- # when PackageDependencyReference
66
- # HostProxyOpsFileInvocationBuilder.new(self, true)
67
-
68
- # # we know we're dealing with a directory reference or OpsFile reference outside of the bundle dir, so we want to reference
69
- # # the specified ops file with respect to the root directory, and not with respect to the bundle dir
70
- # when DirectoryReference, OpsFileReference
71
- # HostProxyOpsFileInvocationBuilder.new(self, false)
72
- # end
73
-
74
- # invocation_builder.send(symbol_name, *args, **kwargs, &block)
75
- # end
76
- # methods_defined << symbol_name
77
- # end
78
- # end
79
-
80
- # # define methods for every Namespace or OpsFile within the namespace that the OpsFile resides within
81
- # sibling_symbol_table = Set.new
82
- # sibling_symbol_table |= ops_file.dirname.glob("*.ops").map {|ops_file_path| ops_file_path.basename(".ops").to_s } # OpsFiles
83
- # sibling_symbol_table |= ops_file.dirname.glob("*").select(&:directory?).map {|dir_path| dir_path.basename.to_s } # Namespaces
84
- # sibling_symbol_table.each do |symbol_name|
85
- # unless methods_defined.include? symbol_name
86
- # # puts "2. defining: #{symbol_name}(...)"
87
- # klass.define_method(symbol_name) do |*args, **kwargs, &block|
88
- # invocation_builder = HostProxyOpsFileInvocationBuilder.new(self, false)
89
- # invocation_builder.invoke(symbol_name, *args, **kwargs, &block)
90
- # end
91
- # methods_defined << symbol_name
92
- # end
93
- # end
94
-
95
- # klass
96
- # end
97
11
 
98
12
  def self.define_host_proxy_class(ops_file)
99
13
  klass = Class.new(HostProxy)
@@ -112,31 +26,16 @@ module OpsWalrus
112
26
  # we know we're dealing with a package dependency reference, so we want to run an ops file contained within the bundle directory,
113
27
  # therefore, we want to reference the specified ops file with respect to the bundle dir
114
28
  when PackageDependencyReference
115
- 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)
116
30
 
117
31
  # we know we're dealing with a directory reference or OpsFile reference outside of the bundle dir, so we want to reference
118
32
  # the specified ops file with respect to the root directory, and not with respect to the bundle dir
119
33
  when DirectoryReference, OpsFileReference
120
- 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)
121
35
  end
122
36
 
123
37
  invocation_context._invoke(*args, **kwargs)
124
38
 
125
-
126
-
127
- # invocation_builder = case import_reference
128
- # # we know we're dealing with a package dependency reference, so we want to run an ops file contained within the bundle directory,
129
- # # therefore, we want to reference the specified ops file with respect to the bundle dir
130
- # when PackageDependencyReference
131
- # HostProxyOpsFileInvocationBuilder.new(self, true)
132
-
133
- # # we know we're dealing with a directory reference or OpsFile reference outside of the bundle dir, so we want to reference
134
- # # the specified ops file with respect to the root directory, and not with respect to the bundle dir
135
- # when DirectoryReference, OpsFileReference
136
- # HostProxyOpsFileInvocationBuilder.new(self, false)
137
- # end
138
-
139
- # invocation_builder.send(symbol_name, *args, **kwargs, &block)
140
39
  end
141
40
  methods_defined << symbol_name
142
41
  end
@@ -150,10 +49,7 @@ module OpsWalrus
150
49
  unless methods_defined.include? symbol_name
151
50
  # puts "2. defining: #{symbol_name}(...)"
152
51
  klass.define_method(symbol_name) do |*args, **kwargs, &block|
153
- # invocation_builder = HostProxyOpsFileInvocationBuilder.new(self, false)
154
- # invocation_builder.invoke(symbol_name, *args, **kwargs, &block)
155
-
156
- invocation_context = RemoteImportInvocationContext.new(@runtime_env, self, namespace_or_ops_file, false)
52
+ invocation_context = RemoteImportInvocationContext.new(@runtime_env, self, namespace_or_ops_file, false, prompt_for_sudo_password: !!ssh_password)
157
53
  invocation_context._invoke(*args, **kwargs)
158
54
  end
159
55
  methods_defined << symbol_name
@@ -202,6 +98,7 @@ module OpsWalrus
202
98
  return ["", "", 0] if !desc_or_cmd && !cmd && !block # we were told to do nothing; like hitting enter at the bash prompt; we can do nothing successfully
203
99
 
204
100
  description = desc_or_cmd if cmd || block
101
+ description = WalrusLang.render(description, block.binding) if description && block
205
102
  cmd = block.call if block
206
103
  cmd ||= desc_or_cmd
207
104
 
@@ -210,13 +107,14 @@ module OpsWalrus
210
107
  #cmd = Shellwords.escape(cmd)
211
108
 
212
109
  if App.instance.report_mode?
110
+ puts Style.green("*" * 80)
213
111
  if self.alias
214
- print "[#{self.alias} | #{host}] "
112
+ print "[#{Style.blue(self.alias)} | #{Style.blue(host)}] "
215
113
  else
216
- print "[#{host}] "
114
+ print "[#{Style.blue(host)}] "
217
115
  end
218
116
  print "#{description}: " if description
219
- puts cmd
117
+ puts Style.yellow(cmd)
220
118
  end
221
119
 
222
120
  return unless cmd && !cmd.strip.empty?
@@ -225,9 +123,12 @@ module OpsWalrus
225
123
  # puts "shell: #{cmd.inspect}"
226
124
  # puts "sudo_password: #{sudo_password}"
227
125
 
228
- sshkit_cmd = execute_cmd(cmd, input: input)
229
-
230
- [sshkit_cmd.full_stdout, sshkit_cmd.full_stderr, sshkit_cmd.exit_status]
126
+ if App.instance.dry_run?
127
+ ["", "", 0]
128
+ else
129
+ sshkit_cmd = execute_cmd(cmd, input: input)
130
+ [sshkit_cmd.full_stdout, sshkit_cmd.full_stderr, sshkit_cmd.exit_status]
131
+ end
231
132
  end
232
133
 
233
134
  # def init_brew
@@ -240,7 +141,13 @@ module OpsWalrus
240
141
  # e.g. /home/linuxbrew/.linuxbrew/bin/gem exec -g opswalrus ops run echo.ops args:foo args:bar
241
142
 
242
143
  # cmd = "/home/linuxbrew/.linuxbrew/bin/gem exec -g opswalrus ops"
243
- cmd = "/home/linuxbrew/.linuxbrew/bin/gem exec -g opswalrus ops"
144
+ local_hostname_for_remote_host = if self.alias
145
+ "#{self.alias} | #{host}"
146
+ else
147
+ host
148
+ end
149
+
150
+ cmd = "OPSWALRUS_LOCAL_HOSTNAME='#{local_hostname_for_remote_host}'; /home/linuxbrew/.linuxbrew/bin/gem exec -g opswalrus ops"
244
151
  cmd << " -v" if verbose
245
152
  cmd << " #{ops_command.to_s}"
246
153
  cmd << " #{ops_command_options.to_s}" if ops_command_options