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 +4 -4
- data/Gemfile.lock +18 -1
- data/lib/opswalrus/app.rb +52 -18
- data/lib/opswalrus/bootstrap.sh +1 -0
- data/lib/opswalrus/bundler.rb +18 -34
- data/lib/opswalrus/cli.rb +24 -10
- data/lib/opswalrus/host.rb +21 -114
- data/lib/opswalrus/interaction_handlers.rb +17 -16
- data/lib/opswalrus/invocation.rb +71 -41
- data/lib/opswalrus/local_non_blocking_backend.rb +0 -1
- data/lib/opswalrus/operation_runner.rb +32 -17
- data/lib/opswalrus/ops_file.rb +3 -2
- data/lib/opswalrus/ops_file_script.rb +81 -10
- data/lib/opswalrus/ops_file_script_dsl.rb +13 -69
- data/lib/opswalrus/package_file.rb +11 -11
- data/lib/opswalrus/runtime_environment.rb +21 -41
- data/lib/opswalrus/version.rb +1 -1
- data/lib/opswalrus.rb +1 -1
- data/opswalrus.gemspec +4 -2
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2ce759171a0342644a1e3e2c94555299b093095b1684a69e11142fe29292da4
|
4
|
+
data.tar.gz: 75f4cab88e00038c73df02d69718b5cd067f3ed69150c192335894128ef912d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
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
|
-
|
95
|
-
|
96
|
-
|
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
|
-
@
|
129
|
+
@logger.level <= 1
|
101
130
|
end
|
102
131
|
|
103
132
|
def debug?
|
104
|
-
@
|
133
|
+
@logger.level <= 0
|
134
|
+
end
|
135
|
+
|
136
|
+
def fatal(*args)
|
137
|
+
@logger.fatal(*args)
|
105
138
|
end
|
106
139
|
|
107
|
-
def error(
|
108
|
-
@logger.error(
|
140
|
+
def error(*args)
|
141
|
+
@logger.error(*args)
|
109
142
|
end
|
110
143
|
|
111
|
-
def warn(
|
112
|
-
@logger.warn(
|
144
|
+
def warn(*args)
|
145
|
+
@logger.warn(*args)
|
113
146
|
end
|
114
147
|
|
115
|
-
def log(
|
116
|
-
@logger.info(
|
148
|
+
def log(*args)
|
149
|
+
@logger.info(*args)
|
117
150
|
end
|
151
|
+
alias_method :info, :log
|
118
152
|
|
119
|
-
def debug(
|
120
|
-
@logger.debug(
|
153
|
+
def debug(*args)
|
154
|
+
@logger.debug(*args)
|
121
155
|
end
|
122
156
|
|
123
|
-
def trace(
|
124
|
-
@logger.trace(
|
157
|
+
def trace(*args)
|
158
|
+
@logger.trace(*args)
|
125
159
|
end
|
126
160
|
|
127
161
|
def set_pwd(pwd)
|
data/lib/opswalrus/bootstrap.sh
CHANGED
@@ -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
|
data/lib/opswalrus/bundler.rb
CHANGED
@@ -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
|
-
|
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 =
|
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["
|
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
|
-
|
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
|
|
data/lib/opswalrus/host.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
229
|
-
|
230
|
-
|
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
|
-
|
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
|