opswalrus 1.0.49 → 1.0.50
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/Gemfile.lock +1 -1
- data/lib/opswalrus/_shell.ops +9 -0
- data/lib/opswalrus/app.rb +28 -5
- data/lib/opswalrus/bootstrap.sh +10 -1
- data/lib/opswalrus/bundler.rb +43 -13
- data/lib/opswalrus/cli.rb +44 -2
- data/lib/opswalrus/host.rb +40 -12
- data/lib/opswalrus/interaction_handlers.rb +10 -1
- data/lib/opswalrus/invocation.rb +4 -3
- data/lib/opswalrus/ops_file.rb +1 -1
- data/lib/opswalrus/ops_file_script_dsl.rb +92 -84
- data/lib/opswalrus/package_file.rb +4 -4
- data/lib/opswalrus/patches.rb +24 -0
- data/lib/opswalrus/runtime_environment.rb +3 -0
- data/lib/opswalrus/version.rb +1 -1
- data/vms/web-ubuntu/Vagrantfile +2 -2
- metadata +4 -3
- /data/lib/opswalrus/{bootstrap.ops → _bootstrap.ops} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20cc50a607aa6aec146b62eb5dbef09a908c5485f8e0d3dbc39cf5bf9a92895e
|
|
4
|
+
data.tar.gz: b27cdf6497c28f6ced9be489365003bad03ddb02e6c1285e76c45e6a5ee5d52b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec22d55f8417db680b98d0651855fd83589f0b2428c26be7279f7a2b62582120f4eafdb473b4df9004f98934508cf46f9686a1a28fe8c2adf83eadc82b2a0a38
|
|
7
|
+
data.tar.gz: 7eb26d1957c2c8115ccaa06b497418f635a4876279c7a4ee5e16eea10546d80303af209a585d4b69ad02f15cca5ce0ea468af86e974947c6283a7998bd8e6426
|
data/Gemfile.lock
CHANGED
data/lib/opswalrus/app.rb
CHANGED
|
@@ -31,7 +31,7 @@ module OpsWalrus
|
|
|
31
31
|
@instance ||= new(*args)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
LOCAL_SUDO_PASSWORD_PROMPT = "[
|
|
34
|
+
LOCAL_SUDO_PASSWORD_PROMPT = "[opswalrus] Please enter sudo password to run sudo in local environment: "
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
attr_reader :local_hostname
|
|
@@ -56,7 +56,7 @@ module OpsWalrus
|
|
|
56
56
|
@inventory_tag_selections = []
|
|
57
57
|
@params = nil
|
|
58
58
|
@pwd = pwd.to_pathname
|
|
59
|
-
@bundler = Bundler.new(@pwd)
|
|
59
|
+
@bundler = Bundler.new(self, @pwd)
|
|
60
60
|
@local_hostname = "localhost"
|
|
61
61
|
@mode = :report # :report | :script
|
|
62
62
|
@dry_run = false
|
|
@@ -173,7 +173,7 @@ module OpsWalrus
|
|
|
173
173
|
|
|
174
174
|
def set_pwd(pwd)
|
|
175
175
|
@pwd = pwd.to_pathname
|
|
176
|
-
@bundler = Bundler.new(@pwd)
|
|
176
|
+
@bundler = Bundler.new(self, @pwd)
|
|
177
177
|
end
|
|
178
178
|
|
|
179
179
|
def pwd
|
|
@@ -217,23 +217,46 @@ module OpsWalrus
|
|
|
217
217
|
|
|
218
218
|
def bootstrap()
|
|
219
219
|
set_pwd(__FILE__.to_pathname.dirname)
|
|
220
|
-
bootstrap_ops_file = OpsFile.new(self, __FILE__.to_pathname.dirname.join("
|
|
220
|
+
bootstrap_ops_file = OpsFile.new(self, __FILE__.to_pathname.dirname.join("_bootstrap.ops"))
|
|
221
221
|
op = OperationRunner.new(self, bootstrap_ops_file)
|
|
222
222
|
op.run([], params_json_hash: @params)
|
|
223
223
|
end
|
|
224
224
|
|
|
225
|
+
def shell(command)
|
|
226
|
+
set_pwd(__FILE__.to_pathname.dirname)
|
|
227
|
+
shell_ops_file = OpsFile.new(self, __FILE__.to_pathname.dirname.join("_shell.ops"))
|
|
228
|
+
op = OperationRunner.new(self, shell_ops_file)
|
|
229
|
+
puts "running #{command}"
|
|
230
|
+
result = op.run([], params_json_hash: {"command" => command})
|
|
231
|
+
puts "result class=#{result.class}"
|
|
232
|
+
exit_status = result.exit_status
|
|
233
|
+
stdout = JSON.pretty_generate(result.value)
|
|
234
|
+
output = if exit_status == 0
|
|
235
|
+
Style.green(stdout)
|
|
236
|
+
else
|
|
237
|
+
Style.red(stdout)
|
|
238
|
+
end
|
|
239
|
+
puts output
|
|
240
|
+
exit_status
|
|
241
|
+
rescue Error => e
|
|
242
|
+
puts "Error: #{e.message}"
|
|
243
|
+
1
|
|
244
|
+
end
|
|
245
|
+
|
|
225
246
|
# args is of the form ["github.com/davidkellis/my-package/sub-package1", "operation1", "arg1:val1", "arg2:val2", "arg3:val3"]
|
|
226
247
|
# if the first argument is the path to a .ops file, then treat it as a local path, and add the containing package
|
|
227
248
|
# to the load path
|
|
228
249
|
# otherwise, copy the
|
|
229
250
|
# returns the exit status code that the script should terminate with
|
|
230
|
-
def run(package_operation_and_args)
|
|
251
|
+
def run(package_operation_and_args, update_bundle: false)
|
|
231
252
|
return 0 if package_operation_and_args.empty?
|
|
232
253
|
|
|
233
254
|
ops_file_path, operation_kv_args, tmp_bundle_root_dir = get_entry_point_ops_file_and_args(package_operation_and_args)
|
|
234
255
|
|
|
235
256
|
ops_file = load_entry_point_ops_file(ops_file_path, tmp_bundle_root_dir)
|
|
236
257
|
|
|
258
|
+
bundler.update if update_bundle
|
|
259
|
+
|
|
237
260
|
debug "Running: #{ops_file.ops_file_path}"
|
|
238
261
|
|
|
239
262
|
op = OperationRunner.new(self, ops_file)
|
data/lib/opswalrus/bootstrap.sh
CHANGED
|
@@ -27,7 +27,7 @@ if [ -x $RTX ]; then
|
|
|
27
27
|
|
|
28
28
|
# make sure the latest opswalrus gem is installed
|
|
29
29
|
# todo: figure out how to install this differently, so that test versions will work
|
|
30
|
-
gem install opswalrus
|
|
30
|
+
# gem install opswalrus
|
|
31
31
|
# $GEM_CMD install opswalrus
|
|
32
32
|
$RTX reshim
|
|
33
33
|
|
|
@@ -60,6 +60,9 @@ if echo $OS | grep -q 'ubuntu'; then
|
|
|
60
60
|
elif echo $OS | grep -q 'fedora'; then
|
|
61
61
|
sudo dnf groupinstall -y 'Development Tools'
|
|
62
62
|
sudo dnf -yq install procps-ng curl file git
|
|
63
|
+
elif echo $OS | grep -q 'rocky'; then
|
|
64
|
+
sudo dnf groupinstall -y 'Development Tools'
|
|
65
|
+
sudo dnf -yq install procps-ng curl file git
|
|
63
66
|
elif echo $OS | grep -q 'arch'; then
|
|
64
67
|
sudo pacman -Syu --noconfirm --needed base-devel procps-ng curl file git
|
|
65
68
|
else
|
|
@@ -121,6 +124,9 @@ if echo $OS | grep -q 'ubuntu'; then
|
|
|
121
124
|
elif echo $OS | grep -q 'fedora'; then
|
|
122
125
|
# from https://github.com/rbenv/ruby-build/wiki#suggested-build-environment
|
|
123
126
|
sudo yum install -y gcc patch bzip2 openssl-devel libyaml-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel
|
|
127
|
+
elif echo $OS | grep -q 'rocky'; then
|
|
128
|
+
sudo yum --enablerepo=powertools install -y libyaml-devel libffi-devel
|
|
129
|
+
sudo yum install -y gcc patch bzip2 openssl-devel libyaml-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel
|
|
124
130
|
elif echo $OS | grep -q 'arch'; then
|
|
125
131
|
# from https://github.com/rbenv/ruby-build/wiki#suggested-build-environment
|
|
126
132
|
sudo pacman -Syu --noconfirm --needed base-devel rust libffi libyaml openssl zlib
|
|
@@ -150,6 +156,9 @@ if echo $OS | grep -q 'ubuntu'; then
|
|
|
150
156
|
sudo needrestart -q -r a
|
|
151
157
|
elif echo $OS | grep -q 'fedora'; then
|
|
152
158
|
sudo dnf -yq install age
|
|
159
|
+
elif echo $OS | grep -q 'rocky'; then
|
|
160
|
+
sudo curl -o /usr/local/bin/age https://dl.filippo.io/age/latest?for=linux/amd64
|
|
161
|
+
sudo chmod 755 /usr/local/bin/age
|
|
153
162
|
elif echo $OS | grep -q 'arch'; then
|
|
154
163
|
sudo pacman -Syu --noconfirm --needed age
|
|
155
164
|
else
|
data/lib/opswalrus/bundler.rb
CHANGED
|
@@ -11,9 +11,11 @@ module OpsWalrus
|
|
|
11
11
|
|
|
12
12
|
include Traversable
|
|
13
13
|
|
|
14
|
+
attr_accessor :app
|
|
14
15
|
attr_accessor :pwd
|
|
15
16
|
|
|
16
|
-
def initialize(working_directory_path)
|
|
17
|
+
def initialize(app, working_directory_path)
|
|
18
|
+
@app = app
|
|
17
19
|
@pwd = working_directory_path.to_pathname
|
|
18
20
|
@bundle_dir = @pwd.join(BUNDLE_DIR)
|
|
19
21
|
end
|
|
@@ -53,20 +55,25 @@ module OpsWalrus
|
|
|
53
55
|
# bundler_for_package.include_directory_in_bundle_as_self_pkg(pwd)
|
|
54
56
|
# end
|
|
55
57
|
|
|
56
|
-
def update
|
|
58
|
+
def update()
|
|
57
59
|
delete_pwd_bundle_directory
|
|
58
60
|
ensure_pwd_bundle_directory_exists
|
|
59
61
|
|
|
60
62
|
package_yaml_files = pwd.glob("./**/package.yaml") - pwd.glob("./**/#{BUNDLE_DIR}/**/package.yaml")
|
|
61
63
|
package_files_within_pwd = package_yaml_files.map {|path| PackageFile.new(path.realpath) }
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
download_package_dependency_tree(package_files_within_pwd)
|
|
66
|
+
|
|
67
|
+
ops_files = pwd.glob("./**/*.ops") - pwd.glob("./**/#{BUNDLE_DIR}/**/*.ops")
|
|
68
|
+
ops_files_within_pwd = ops_files.map {|path| OpsFile.new(@app, path.realpath) }
|
|
69
|
+
|
|
70
|
+
download_import_dependencies(ops_files_within_pwd)
|
|
64
71
|
end
|
|
65
72
|
|
|
66
|
-
# downloads all transitive package dependencies associated with
|
|
73
|
+
# downloads all transitive package dependencies associated with ops_files_and_package_files
|
|
67
74
|
# all downloaded packages are placed into @bundle_dir
|
|
68
|
-
def
|
|
69
|
-
package_files = ops_files_and_package_files.map(&:package_file).compact.uniq
|
|
75
|
+
def download_package_dependency_tree(*ops_files_and_package_files)
|
|
76
|
+
package_files = ops_files_and_package_files.flatten.map(&:package_file).compact.uniq
|
|
70
77
|
|
|
71
78
|
package_files.each do |root_package_file|
|
|
72
79
|
pre_order_traverse(root_package_file) do |package_file|
|
|
@@ -78,11 +85,29 @@ module OpsWalrus
|
|
|
78
85
|
end
|
|
79
86
|
end
|
|
80
87
|
|
|
88
|
+
def download_import_dependencies(*ops_files)
|
|
89
|
+
ops_files.flatten.each do |ops_file|
|
|
90
|
+
ops_file.imports.each do |local_name, import_reference|
|
|
91
|
+
case import_reference
|
|
92
|
+
when PackageDependencyReference, DynamicPackageImportReference
|
|
93
|
+
package_reference = import_reference.package_reference
|
|
94
|
+
download_package(ops_file.dirname, ops_file.ops_file_path, package_reference)
|
|
95
|
+
when DirectoryReference
|
|
96
|
+
# noop
|
|
97
|
+
when OpsFileReference
|
|
98
|
+
# noop
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
81
104
|
# returns the array of the destination directories that the packages that ops_file depend on were downloaded to
|
|
82
105
|
# e.g. [dir_path1, dir_path2, dir_path3, ...]
|
|
83
106
|
def download_package_dependencies(package_file)
|
|
107
|
+
containing_directory = package_file.containing_directory
|
|
108
|
+
package_file_source = package_file.package_file_path
|
|
84
109
|
package_file.dependencies.map do |local_name, package_reference|
|
|
85
|
-
download_package(
|
|
110
|
+
download_package(containing_directory, package_file_source, package_reference)
|
|
86
111
|
end
|
|
87
112
|
end
|
|
88
113
|
|
|
@@ -107,7 +132,9 @@ module OpsWalrus
|
|
|
107
132
|
|
|
108
133
|
# This method downloads a package_url that is a dependency referenced in the specified package_file
|
|
109
134
|
# returns the destination directory that the package was downloaded to
|
|
110
|
-
|
|
135
|
+
#
|
|
136
|
+
# relative_base_path is the relative base path that any relative file paths captured in the package_reference should be evaluated relative to
|
|
137
|
+
def download_package(relative_base_path, source_of_package_reference, package_reference)
|
|
111
138
|
ensure_pwd_bundle_directory_exists
|
|
112
139
|
|
|
113
140
|
local_name = package_reference.local_name
|
|
@@ -116,22 +143,25 @@ module OpsWalrus
|
|
|
116
143
|
|
|
117
144
|
destination_package_path = @bundle_dir.join(package_reference.import_resolution_dirname)
|
|
118
145
|
|
|
119
|
-
App.instance.log("Downloading #{package_reference} referenced in #{package_file.package_file_path} to #{destination_package_path}")
|
|
146
|
+
# App.instance.log("Downloading #{package_reference} referenced in #{package_file.package_file_path} to #{destination_package_path}")
|
|
147
|
+
App.instance.log("Downloading #{package_reference} referenced in #{source_of_package_reference} to #{destination_package_path}")
|
|
120
148
|
|
|
121
149
|
# we return early here under the assumption that an already downloaded package/version combo will not
|
|
122
150
|
# differ if we download it again multiple times to the same location
|
|
123
151
|
if destination_package_path.exist?
|
|
124
|
-
App.instance.log("Skipping #{package_reference} referenced in #{
|
|
152
|
+
App.instance.log("Skipping #{package_reference} referenced in #{source_of_package_reference} since it already has been downloaded to #{destination_package_path}")
|
|
125
153
|
return destination_package_path
|
|
126
154
|
end
|
|
127
155
|
# FileUtils.remove_dir(destination_package_path) if destination_package_path.exist?
|
|
128
156
|
|
|
129
|
-
download_package_contents(package_file, local_name, package_url, version, destination_package_path)
|
|
157
|
+
# download_package_contents(package_file.containing_directory, local_name, package_url, version, destination_package_path)
|
|
158
|
+
download_package_contents(relative_base_path, local_name, package_url, version, destination_package_path)
|
|
130
159
|
|
|
131
160
|
destination_package_path
|
|
132
161
|
end
|
|
133
162
|
|
|
134
|
-
|
|
163
|
+
# relative_base_path is a Pathname
|
|
164
|
+
def download_package_contents(relative_base_path, local_name, package_url, version, destination_package_path)
|
|
135
165
|
package_path = package_url.to_pathname
|
|
136
166
|
package_path = package_path.to_s.gsub(/^~/, Dir.home).to_pathname
|
|
137
167
|
App.instance.trace("download_package_contents #{package_path}")
|
|
@@ -148,7 +178,7 @@ module OpsWalrus
|
|
|
148
178
|
end
|
|
149
179
|
end
|
|
150
180
|
if package_path.relative? # relative path reference
|
|
151
|
-
rebased_path =
|
|
181
|
+
rebased_path = relative_base_path.join(package_path)
|
|
152
182
|
if rebased_path.exist?
|
|
153
183
|
return case
|
|
154
184
|
when rebased_path.directory?
|
data/lib/opswalrus/cli.rb
CHANGED
|
@@ -131,11 +131,46 @@ module OpsWalrus
|
|
|
131
131
|
$app.set_log_level(global_options[:trace] && :trace || global_options[:debug] && :debug || global_options[:verbose] && :info || :warn)
|
|
132
132
|
|
|
133
133
|
hosts = global_options[:hosts]
|
|
134
|
+
$app.set_inventory_hosts(hosts)
|
|
135
|
+
|
|
134
136
|
tags = global_options[:tags]
|
|
137
|
+
$app.set_inventory_tags(tags)
|
|
138
|
+
|
|
139
|
+
id_files = global_options[:id]
|
|
140
|
+
id_files = OpsWalrus.env_specified_age_ids if id_files.empty?
|
|
141
|
+
|
|
142
|
+
$app.set_identity_files(id_files)
|
|
143
|
+
|
|
144
|
+
dry_run = [:noop, :dryrun, :dry_run].any? {|sym| global_options[sym] || options[sym] }
|
|
145
|
+
$app.dry_run! if dry_run
|
|
146
|
+
|
|
147
|
+
$app.bootstrap()
|
|
148
|
+
end
|
|
149
|
+
end
|
|
135
150
|
|
|
151
|
+
desc "Run a shell command on one or more remote hosts"
|
|
152
|
+
long_desc 'Run a shell command on one or more remote hosts'
|
|
153
|
+
command :shell do |c|
|
|
154
|
+
c.switch :pass, desc: "Prompt for a sudo password"
|
|
155
|
+
c.flag [:u, :user], desc: "Specify the user that the operation will run as"
|
|
156
|
+
|
|
157
|
+
# dry run
|
|
158
|
+
c.switch :noop, desc: "Perform a dry run"
|
|
159
|
+
c.switch :dryrun, desc: "Perform a dry run"
|
|
160
|
+
c.switch :dry_run, desc: "Perform a dry run"
|
|
161
|
+
|
|
162
|
+
c.action do |global_options, options, args|
|
|
163
|
+
$app.set_log_level(global_options[:trace] && :trace || global_options[:debug] && :debug || global_options[:verbose] && :info || :warn)
|
|
164
|
+
|
|
165
|
+
hosts = global_options[:hosts]
|
|
136
166
|
$app.set_inventory_hosts(hosts)
|
|
167
|
+
|
|
168
|
+
tags = global_options[:tags]
|
|
137
169
|
$app.set_inventory_tags(tags)
|
|
138
170
|
|
|
171
|
+
user = options[:user]
|
|
172
|
+
$app.set_sudo_user(user) if user
|
|
173
|
+
|
|
139
174
|
id_files = global_options[:id]
|
|
140
175
|
id_files = OpsWalrus.env_specified_age_ids if id_files.empty?
|
|
141
176
|
|
|
@@ -144,7 +179,13 @@ module OpsWalrus
|
|
|
144
179
|
dry_run = [:noop, :dryrun, :dry_run].any? {|sym| global_options[sym] || options[sym] }
|
|
145
180
|
$app.dry_run! if dry_run
|
|
146
181
|
|
|
147
|
-
|
|
182
|
+
if options[:pass]
|
|
183
|
+
$app.prompt_sudo_password
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
exit_status = $app.shell(args.join(" "))
|
|
187
|
+
|
|
188
|
+
exit_now!("error", exit_status) unless exit_status == 0
|
|
148
189
|
end
|
|
149
190
|
end
|
|
150
191
|
|
|
@@ -152,6 +193,7 @@ module OpsWalrus
|
|
|
152
193
|
long_desc 'Run the specified operation found within the specified package'
|
|
153
194
|
arg 'args', :multiple
|
|
154
195
|
command :run do |c|
|
|
196
|
+
c.switch [:b, :bundle], desc: "Update bundle prior to running the specified operation"
|
|
155
197
|
c.switch :pass, desc: "Prompt for a sudo password"
|
|
156
198
|
c.switch :script, desc: "Script mode"
|
|
157
199
|
|
|
@@ -194,7 +236,7 @@ module OpsWalrus
|
|
|
194
236
|
$app.script_mode!
|
|
195
237
|
end
|
|
196
238
|
|
|
197
|
-
exit_status = $app.run(args)
|
|
239
|
+
exit_status = $app.run(args, update_bundle: options[:bundle])
|
|
198
240
|
|
|
199
241
|
exit_now!("error", exit_status) unless exit_status == 0
|
|
200
242
|
end
|
data/lib/opswalrus/host.rb
CHANGED
|
@@ -30,7 +30,7 @@ module OpsWalrus
|
|
|
30
30
|
invocation_context = case import_reference
|
|
31
31
|
# we know we're dealing with a package dependency reference, so we want to run an ops file contained within the bundle directory,
|
|
32
32
|
# therefore, we want to reference the specified ops file with respect to the bundle dir
|
|
33
|
-
when PackageDependencyReference
|
|
33
|
+
when PackageDependencyReference, DynamicPackageImportReference
|
|
34
34
|
RemoteImportInvocationContext.new(@runtime_env, self, namespace_or_ops_file, true, ops_prompt_for_sudo_password: !!ssh_password)
|
|
35
35
|
|
|
36
36
|
# we know we're dealing with a directory reference or OpsFile reference outside of the bundle dir, so we want to reference
|
|
@@ -261,12 +261,12 @@ module OpsWalrus
|
|
|
261
261
|
|
|
262
262
|
# cmd = "OPS_GEM=\"#{OPS_GEM}\" OPSWALRUS_LOCAL_HOSTNAME='#{local_hostname_for_remote_host}'; $OPS_GEM exec --conservative -g opswalrus ops"
|
|
263
263
|
cmd = "OPSWALRUS_LOCAL_HOSTNAME='#{local_hostname_for_remote_host}' eval #{OPS_CMD}"
|
|
264
|
-
if App.instance.
|
|
265
|
-
cmd << " --
|
|
264
|
+
if App.instance.trace?
|
|
265
|
+
cmd << " --trace"
|
|
266
266
|
elsif App.instance.debug?
|
|
267
267
|
cmd << " --debug"
|
|
268
|
-
elsif App.instance.
|
|
269
|
-
cmd << " --
|
|
268
|
+
elsif App.instance.info?
|
|
269
|
+
cmd << " --verbose"
|
|
270
270
|
end
|
|
271
271
|
cmd << " #{ops_command.to_s}"
|
|
272
272
|
cmd << " #{ops_command_options.to_s}" if ops_command_options
|
|
@@ -300,32 +300,56 @@ module OpsWalrus
|
|
|
300
300
|
@props[name] || @default_props[name]
|
|
301
301
|
end
|
|
302
302
|
|
|
303
|
+
def ssh_session
|
|
304
|
+
@sshkit_backend
|
|
305
|
+
end
|
|
306
|
+
|
|
303
307
|
end
|
|
304
308
|
|
|
305
309
|
class Host
|
|
306
310
|
include HostDSL
|
|
307
311
|
|
|
308
|
-
|
|
309
|
-
|
|
312
|
+
# ssh_uri is a string of the form:
|
|
313
|
+
# - hostname
|
|
314
|
+
# - user@hostname
|
|
315
|
+
# - hostname:port
|
|
316
|
+
# - user@hostname:port
|
|
317
|
+
def initialize(ssh_uri, tags = [], props = {}, default_props = {}, hosts_file = nil)
|
|
318
|
+
@ssh_uri = ssh_uri
|
|
319
|
+
@host = nil
|
|
310
320
|
@tags = tags.to_set
|
|
311
321
|
@props = props.is_a?(Array) ? {"tags" => props} : props.to_h
|
|
312
322
|
@default_props = default_props
|
|
313
323
|
@hosts_file = hosts_file
|
|
314
324
|
@tmp_ssh_key_files = []
|
|
325
|
+
parse_ssh_uri!
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def parse_ssh_uri!
|
|
329
|
+
if match = /^\s*((?<user>.*?)@)?(?<host>.*?)(:(?<port>[0-9]+))?\s*$/.match(@ssh_uri)
|
|
330
|
+
@host ||= match[:host] if match[:host]
|
|
331
|
+
@props["user"] ||= match[:user] if match[:user]
|
|
332
|
+
@props["port"] ||= match[:port].to_i if match[:port]
|
|
333
|
+
end
|
|
315
334
|
end
|
|
316
335
|
|
|
317
336
|
# secret_ref: SecretRef
|
|
318
337
|
# returns the decrypted value referenced by the supplied SecretRef
|
|
319
338
|
def dereference_secret_if_needed(secret_ref)
|
|
320
339
|
if secret_ref.is_a? SecretRef
|
|
340
|
+
raise "Host #{self} not read from hosts file so no secrets can be dereferenced." unless @hosts_file
|
|
321
341
|
@hosts_file.read_secret(secret_ref.to_s)
|
|
322
342
|
else
|
|
323
343
|
secret_ref
|
|
324
344
|
end
|
|
325
345
|
end
|
|
326
346
|
|
|
347
|
+
def ssh_uri
|
|
348
|
+
@ssh_uri
|
|
349
|
+
end
|
|
350
|
+
|
|
327
351
|
def host
|
|
328
|
-
@
|
|
352
|
+
@host
|
|
329
353
|
end
|
|
330
354
|
|
|
331
355
|
def alias
|
|
@@ -337,7 +361,7 @@ module OpsWalrus
|
|
|
337
361
|
end
|
|
338
362
|
|
|
339
363
|
def ssh_port
|
|
340
|
-
@props["port"] || @default_props["port"]
|
|
364
|
+
@props["port"] || @default_props["port"] || 22
|
|
341
365
|
end
|
|
342
366
|
|
|
343
367
|
def ssh_user
|
|
@@ -346,6 +370,9 @@ module OpsWalrus
|
|
|
346
370
|
|
|
347
371
|
def ssh_password
|
|
348
372
|
password = @props["password"] || @default_props["password"]
|
|
373
|
+
password ||= begin
|
|
374
|
+
@props["password"] = IO::console.getpass("[opswalrus] Please enter ssh password to connect to #{ssh_user}@#{host}:#{ssh_port}: ")
|
|
375
|
+
end
|
|
349
376
|
dereference_secret_if_needed(password)
|
|
350
377
|
end
|
|
351
378
|
|
|
@@ -354,7 +381,7 @@ module OpsWalrus
|
|
|
354
381
|
end
|
|
355
382
|
|
|
356
383
|
def hash
|
|
357
|
-
@
|
|
384
|
+
@ssh_uri.hash
|
|
358
385
|
end
|
|
359
386
|
|
|
360
387
|
def eql?(other)
|
|
@@ -362,7 +389,7 @@ module OpsWalrus
|
|
|
362
389
|
end
|
|
363
390
|
|
|
364
391
|
def to_s
|
|
365
|
-
@
|
|
392
|
+
@ssh_uri
|
|
366
393
|
end
|
|
367
394
|
|
|
368
395
|
def tag!(*tags)
|
|
@@ -396,7 +423,7 @@ module OpsWalrus
|
|
|
396
423
|
# the various options for net-ssh are captured in https://net-ssh.github.io/ssh/v1/chapter-2.html
|
|
397
424
|
@sshkit_host ||= ::SSHKit::Host.new({
|
|
398
425
|
hostname: host,
|
|
399
|
-
port: ssh_port
|
|
426
|
+
port: ssh_port,
|
|
400
427
|
user: ssh_user || raise("No ssh user specified to connect to #{host}"),
|
|
401
428
|
password: ssh_password,
|
|
402
429
|
keys: keys
|
|
@@ -415,6 +442,7 @@ module OpsWalrus
|
|
|
415
442
|
if key_file_path_or_in_memory_key_text.is_a? SecretRef # we're dealing with an in-memory key file; we need to write it to a tempfile
|
|
416
443
|
tempfile = Tempfile.create
|
|
417
444
|
@tmp_ssh_key_files << tempfile
|
|
445
|
+
raise "Host #{self} not read from hosts file so no secrets can be written." unless @hosts_file
|
|
418
446
|
key_file_contents = @hosts_file.read_secret(key_file_path_or_in_memory_key_text.to_s)
|
|
419
447
|
tempfile.write(key_file_contents)
|
|
420
448
|
tempfile.close # we want to close the file without unlinking so that the editor can write to it
|
|
@@ -4,6 +4,7 @@ module OpsWalrus
|
|
|
4
4
|
|
|
5
5
|
class ScopedMappingInteractionHandler
|
|
6
6
|
STANDARD_SUDO_PASSWORD_PROMPT = /\[sudo\] password for .*?:\s*/
|
|
7
|
+
STANDARD_SSH_PASSWORD_PROMPT = /.*?@.*?'s password:\s*/
|
|
7
8
|
|
|
8
9
|
attr_accessor :input_mappings # Hash[ String | Regex => String ]
|
|
9
10
|
|
|
@@ -13,6 +14,14 @@ module OpsWalrus
|
|
|
13
14
|
@input_mappings = mapping
|
|
14
15
|
end
|
|
15
16
|
|
|
17
|
+
# sudo_password : String | Nil
|
|
18
|
+
def self.mapping_for_ssh_password_prompt(ssh_password)
|
|
19
|
+
password_response = ssh_password && ::SSHKit::InteractionHandler::Password.new("#{ssh_password}\n")
|
|
20
|
+
{
|
|
21
|
+
STANDARD_SSH_PASSWORD_PROMPT => password_response,
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
16
25
|
# sudo_password : String | Nil
|
|
17
26
|
def self.mapping_for_sudo_password(sudo_password)
|
|
18
27
|
password_response = sudo_password && ::SSHKit::InteractionHandler::Password.new("#{sudo_password}\n")
|
|
@@ -51,7 +60,7 @@ module OpsWalrus
|
|
|
51
60
|
end
|
|
52
61
|
new_mapping.merge!(password_mappings) if password_mappings
|
|
53
62
|
|
|
54
|
-
if new_mapping.empty?
|
|
63
|
+
if new_mapping.empty? || new_mapping == @input_mappings
|
|
55
64
|
yield self
|
|
56
65
|
else
|
|
57
66
|
yield ScopedMappingInteractionHandler.new(new_mapping, @log_level)
|
data/lib/opswalrus/invocation.rb
CHANGED
|
@@ -137,9 +137,10 @@ module OpsWalrus
|
|
|
137
137
|
json_kwargs_tempfile.close rescue nil
|
|
138
138
|
File.unlink(json_kwargs_tempfile) rescue nil
|
|
139
139
|
end
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
140
|
+
# todo: make sure this cleanup is present
|
|
141
|
+
# if remote_json_kwargs_tempfile_basename
|
|
142
|
+
# @host_proxy.execute(:rm, "-f", remote_json_kwargs_tempfile_basename)
|
|
143
|
+
# end
|
|
143
144
|
end
|
|
144
145
|
end
|
|
145
146
|
end
|
data/lib/opswalrus/ops_file.rb
CHANGED
|
@@ -163,7 +163,7 @@ module OpsWalrus
|
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
package_uri = import_str
|
|
166
|
-
if Git.repo?(package_uri) # ops file has imported an ad-hoc git repo
|
|
166
|
+
if package_uri = Git.repo?(package_uri) # ops file has imported an ad-hoc git repo
|
|
167
167
|
destination_package_path = app.bundler.dynamic_package_path_for_git_package(package_uri)
|
|
168
168
|
App.instance.trace "DynamicPackageImportReference: #{local_name} -> #{destination_package_path}"
|
|
169
169
|
return DynamicPackageImportReference.new(local_name, DynamicPackageReference.new(local_name, package_uri, nil))
|
|
@@ -47,11 +47,6 @@ module OpsWalrus
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
# BootstrapLinuxHostShellScript = <<~SCRIPT
|
|
51
|
-
# #!/usr/bin/env bash
|
|
52
|
-
# ...
|
|
53
|
-
# SCRIPT
|
|
54
|
-
|
|
55
50
|
module OpsFileScriptDSL
|
|
56
51
|
def ssh_noprep(*args, **kwargs, &block)
|
|
57
52
|
runtime_env = @runtime_env
|
|
@@ -59,48 +54,55 @@ module OpsWalrus
|
|
|
59
54
|
hosts = inventory(*args, **kwargs).map {|host| host_proxy_class.new(runtime_env, host) }
|
|
60
55
|
sshkit_hosts = hosts.map(&:sshkit_host)
|
|
61
56
|
sshkit_host_to_ops_host_map = sshkit_hosts.zip(hosts).to_h
|
|
62
|
-
local_host = self
|
|
57
|
+
ops_file_script = local_host = self
|
|
63
58
|
# on sshkit_hosts do |sshkit_host|
|
|
64
59
|
SSHKit::Coordinator.new(sshkit_hosts).each(in: kwargs[:in] || :parallel) do |sshkit_host|
|
|
65
60
|
# in this context, self is an instance of one of the subclasses of SSHKit::Backend::Abstract, e.g. SSHKit::Backend::Netssh
|
|
66
61
|
host = sshkit_host_to_ops_host_map[sshkit_host]
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
62
|
+
sshkit_backend = self # self is an instance of one of the subclasses of SSHKit::Backend::Abstract, e.g. SSHKit::Backend::Netssh
|
|
63
|
+
|
|
64
|
+
ssh_password_interaction_mapping = host.ssh_password && ScopedMappingInteractionHandler.mapping_for_ssh_password_prompt(host.ssh_password)
|
|
65
|
+
runtime_env.handle_input(ssh_password_interaction_mapping, inherit_existing_mappings: true) do |interaction_handler|
|
|
66
|
+
App.instance.debug("OpsFileScriptDSL#ssh input mappings #{interaction_handler.input_mappings.inspect}")
|
|
67
|
+
|
|
68
|
+
begin
|
|
69
|
+
host.set_runtime_env(runtime_env)
|
|
70
|
+
host.set_ops_file_script(ops_file_script)
|
|
71
|
+
host.set_ssh_session_connection(sshkit_backend)
|
|
72
|
+
|
|
73
|
+
# we run the block in the context of the host proxy object, s.t. `self` within the block evaluates to the host proxy object
|
|
74
|
+
retval = host.instance_exec(local_host, &block) # local_host is passed as the argument to the block
|
|
75
|
+
|
|
76
|
+
retval
|
|
77
|
+
rescue SSHKit::Command::Failed => e
|
|
78
|
+
App.instance.error "[!] Command failed:"
|
|
79
|
+
App.instance.error e.message
|
|
80
|
+
rescue Net::SSH::ConnectionTimeout
|
|
81
|
+
App.instance.error "[!] The host '#{host}' not alive!"
|
|
82
|
+
rescue Net::SSH::Timeout
|
|
83
|
+
App.instance.error "[!] The host '#{host}' disconnected/timeouted unexpectedly!"
|
|
84
|
+
rescue Errno::ECONNREFUSED
|
|
85
|
+
App.instance.error "[!] Incorrect port #{host.ssh_port} for #{host}"
|
|
86
|
+
rescue Net::SSH::HostKeyMismatch => e
|
|
87
|
+
App.instance.error "[!] The host fingerprint does not match the last observed fingerprint for #{host}"
|
|
88
|
+
App.instance.error e.message
|
|
89
|
+
App.instance.error "You might try `ssh-keygen -f ~/.ssh/known_hosts -R \"#{host}\"`"
|
|
90
|
+
rescue Net::SSH::AuthenticationFailed
|
|
91
|
+
App.instance.error "Wrong Password: #{host} | #{host.ssh_user}:#{host.ssh_password}"
|
|
92
|
+
rescue Net::SSH::Authentication::DisallowedMethod
|
|
93
|
+
App.instance.error "[!] The host '#{host}' doesn't accept password authentication method."
|
|
94
|
+
rescue Errno::EHOSTUNREACH => e
|
|
95
|
+
App.instance.error "[!] The host '#{host}' is unreachable"
|
|
96
|
+
rescue => e
|
|
97
|
+
App.instance.error e.class
|
|
98
|
+
App.instance.error e.message
|
|
99
|
+
App.instance.error e.backtrace.join("\n")
|
|
100
|
+
ensure
|
|
101
|
+
host.clear_ssh_session
|
|
102
|
+
end
|
|
103
|
+
end # runtime_env.handle_input
|
|
104
|
+
end # SSHKit::Coordinator
|
|
105
|
+
end # def ssh
|
|
104
106
|
|
|
105
107
|
def ssh(*args, **kwargs, &block)
|
|
106
108
|
runtime_env = @runtime_env
|
|
@@ -114,48 +116,54 @@ module OpsWalrus
|
|
|
114
116
|
SSHKit::Coordinator.new(sshkit_hosts).each(in: kwargs[:in] || :parallel) do |sshkit_host|
|
|
115
117
|
# in this context, self is an instance of one of the subclasses of SSHKit::Backend::Abstract, e.g. SSHKit::Backend::Netssh
|
|
116
118
|
host = sshkit_host_to_ops_host_map[sshkit_host]
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
host.
|
|
126
|
-
|
|
127
|
-
|
|
119
|
+
sshkit_backend = self # self is an instance of one of the subclasses of SSHKit::Backend::Abstract, e.g. SSHKit::Backend::Netssh
|
|
120
|
+
|
|
121
|
+
ssh_password_interaction_mapping = host.ssh_password && ScopedMappingInteractionHandler.mapping_for_ssh_password_prompt(host.ssh_password)
|
|
122
|
+
runtime_env.handle_input(ssh_password_interaction_mapping, inherit_existing_mappings: true) do |interaction_handler|
|
|
123
|
+
App.instance.debug("OpsFileScriptDSL#ssh input mappings #{interaction_handler.input_mappings.inspect}")
|
|
124
|
+
|
|
125
|
+
begin
|
|
126
|
+
host.set_runtime_env(runtime_env)
|
|
127
|
+
host.set_ops_file_script(ops_file_script)
|
|
128
|
+
host.set_ssh_session_connection(sshkit_backend)
|
|
129
|
+
|
|
130
|
+
stdout, stderr, exit_status = host._bootstrap_host(true)
|
|
131
|
+
retval = if exit_status == 0
|
|
132
|
+
host._zip_copy_and_run_ops_bundle(local_host, block)
|
|
133
|
+
else
|
|
134
|
+
puts "Failed to bootstrap #{host}. Unable to run operation."
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
retval
|
|
138
|
+
rescue SSHKit::Command::Failed => e
|
|
139
|
+
App.instance.error "[!] Command failed:"
|
|
140
|
+
App.instance.error e.message
|
|
141
|
+
rescue Net::SSH::ConnectionTimeout
|
|
142
|
+
App.instance.error "[!] The host '#{host}' not alive!"
|
|
143
|
+
rescue Net::SSH::Timeout
|
|
144
|
+
App.instance.error "[!] The host '#{host}' disconnected/timeouted unexpectedly!"
|
|
145
|
+
rescue Errno::ECONNREFUSED
|
|
146
|
+
App.instance.error "[!] Incorrect port #{host.ssh_port} for #{host}"
|
|
147
|
+
rescue Net::SSH::HostKeyMismatch => e
|
|
148
|
+
App.instance.error "[!] The host fingerprint does not match the last observed fingerprint for #{host}"
|
|
149
|
+
App.instance.error e.message
|
|
150
|
+
App.instance.error "You might try `ssh-keygen -f ~/.ssh/known_hosts -R \"#{host}\"`"
|
|
151
|
+
rescue Net::SSH::AuthenticationFailed
|
|
152
|
+
App.instance.error "Wrong Password: #{host} | #{host.ssh_user}:#{host.ssh_password}"
|
|
153
|
+
rescue Net::SSH::Authentication::DisallowedMethod
|
|
154
|
+
App.instance.error "[!] The host '#{host}' doesn't accept password authentication method."
|
|
155
|
+
rescue Errno::EHOSTUNREACH => e
|
|
156
|
+
App.instance.error "[!] The host '#{host}' is unreachable"
|
|
157
|
+
rescue => e
|
|
158
|
+
App.instance.error e.class
|
|
159
|
+
App.instance.error e.message
|
|
160
|
+
App.instance.error e.backtrace.join("\n")
|
|
161
|
+
ensure
|
|
162
|
+
host.clear_ssh_session
|
|
128
163
|
end
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
App.instance.error "[!] Command failed:"
|
|
133
|
-
App.instance.error e.message
|
|
134
|
-
rescue Net::SSH::ConnectionTimeout
|
|
135
|
-
App.instance.error "[!] The host '#{host}' not alive!"
|
|
136
|
-
rescue Net::SSH::Timeout
|
|
137
|
-
App.instance.error "[!] The host '#{host}' disconnected/timeouted unexpectedly!"
|
|
138
|
-
rescue Errno::ECONNREFUSED
|
|
139
|
-
App.instance.error "[!] Incorrect port #{port} for #{host}"
|
|
140
|
-
rescue Net::SSH::HostKeyMismatch => e
|
|
141
|
-
App.instance.error "[!] The host fingerprint does not match the last observed fingerprint for #{host}"
|
|
142
|
-
App.instance.error e.message
|
|
143
|
-
App.instance.error "You might try `ssh-keygen -f ~/.ssh/known_hosts -R \"#{host}\"`"
|
|
144
|
-
rescue Net::SSH::AuthenticationFailed
|
|
145
|
-
App.instance.error "Wrong Password: #{host} | #{user}:#{password}"
|
|
146
|
-
rescue Net::SSH::Authentication::DisallowedMethod
|
|
147
|
-
App.instance.error "[!] The host '#{host}' doesn't accept password authentication method."
|
|
148
|
-
rescue Errno::EHOSTUNREACH => e
|
|
149
|
-
App.instance.error "[!] The host '#{host}' is unreachable"
|
|
150
|
-
rescue => e
|
|
151
|
-
App.instance.error e.class
|
|
152
|
-
App.instance.error e.message
|
|
153
|
-
App.instance.error e.backtrace.join("\n")
|
|
154
|
-
ensure
|
|
155
|
-
host.clear_ssh_session
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
end
|
|
164
|
+
end # runtime_env.handle_input
|
|
165
|
+
end # SSHKit::Coordinator
|
|
166
|
+
end # def ssh
|
|
159
167
|
|
|
160
168
|
def current_dir
|
|
161
169
|
File.dirname(File.realpath(@runtime_ops_file_path)).to_pathname
|
|
@@ -72,10 +72,10 @@ module OpsWalrus
|
|
|
72
72
|
self
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
def bundle!
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
end
|
|
75
|
+
# def bundle!
|
|
76
|
+
# bundler_for_package = Bundler.new(dirname)
|
|
77
|
+
# bundler_for_package.update
|
|
78
|
+
# end
|
|
79
79
|
|
|
80
80
|
def dirname
|
|
81
81
|
@package_file_path.dirname
|
data/lib/opswalrus/patches.rb
CHANGED
|
@@ -38,6 +38,10 @@ class String
|
|
|
38
38
|
def string!(default: "")
|
|
39
39
|
self
|
|
40
40
|
end
|
|
41
|
+
|
|
42
|
+
def integer!(default: 0)
|
|
43
|
+
to_i
|
|
44
|
+
end
|
|
41
45
|
end
|
|
42
46
|
|
|
43
47
|
class Integer
|
|
@@ -48,6 +52,10 @@ class Integer
|
|
|
48
52
|
def string!(default: "")
|
|
49
53
|
to_s
|
|
50
54
|
end
|
|
55
|
+
|
|
56
|
+
def integer!(default: 0)
|
|
57
|
+
self
|
|
58
|
+
end
|
|
51
59
|
end
|
|
52
60
|
|
|
53
61
|
class Float
|
|
@@ -58,6 +66,10 @@ class Float
|
|
|
58
66
|
def string!(default: "")
|
|
59
67
|
to_s
|
|
60
68
|
end
|
|
69
|
+
|
|
70
|
+
def integer!(default: 0)
|
|
71
|
+
to_i
|
|
72
|
+
end
|
|
61
73
|
end
|
|
62
74
|
|
|
63
75
|
class NilClass
|
|
@@ -68,6 +80,10 @@ class NilClass
|
|
|
68
80
|
def string!(default: "")
|
|
69
81
|
default
|
|
70
82
|
end
|
|
83
|
+
|
|
84
|
+
def integer!(default: 0)
|
|
85
|
+
default
|
|
86
|
+
end
|
|
71
87
|
end
|
|
72
88
|
|
|
73
89
|
class TrueClass
|
|
@@ -78,6 +94,10 @@ class TrueClass
|
|
|
78
94
|
def string!(default: "")
|
|
79
95
|
to_s
|
|
80
96
|
end
|
|
97
|
+
|
|
98
|
+
def integer!(default: 0)
|
|
99
|
+
default
|
|
100
|
+
end
|
|
81
101
|
end
|
|
82
102
|
|
|
83
103
|
class FalseClass
|
|
@@ -88,4 +108,8 @@ class FalseClass
|
|
|
88
108
|
def string!(default: "")
|
|
89
109
|
to_s
|
|
90
110
|
end
|
|
111
|
+
|
|
112
|
+
def integer!(default: 0)
|
|
113
|
+
default
|
|
114
|
+
end
|
|
91
115
|
end
|
|
@@ -250,6 +250,9 @@ module OpsWalrus
|
|
|
250
250
|
# host will be managed by the local ScopedMappingInteractionHandler running within the instance of the ops command
|
|
251
251
|
# process on the remote host, and the command host will not have any further opportunity to interactively enter
|
|
252
252
|
# any prompts on the remote host
|
|
253
|
+
# All that to say that this initial mapping handler will be used to fill in the sudo password for commands running
|
|
254
|
+
# on the remote host, and it will be the instance of the ops tool running on the remote host that will interactively
|
|
255
|
+
# fill out the password on the remote host
|
|
253
256
|
interaction_handler_mapping_for_sudo_password = ScopedMappingInteractionHandler.mapping_for_sudo_password(sudo_password)
|
|
254
257
|
@interaction_handler = ScopedMappingInteractionHandler.new(interaction_handler_mapping_for_sudo_password)
|
|
255
258
|
|
data/lib/opswalrus/version.rb
CHANGED
data/vms/web-ubuntu/Vagrantfile
CHANGED
|
@@ -23,8 +23,8 @@ Vagrant.configure("2") do |config|
|
|
|
23
23
|
config.vm.provision "shell" do |s|
|
|
24
24
|
ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_ops.pub").first.strip
|
|
25
25
|
s.inline = <<-SHELL
|
|
26
|
-
echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
|
|
27
|
-
echo #{ssh_pub_key} >> /root/.ssh/authorized_keys
|
|
26
|
+
# echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
|
|
27
|
+
# echo #{ssh_pub_key} >> /root/.ssh/authorized_keys
|
|
28
28
|
|
|
29
29
|
sudo sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
|
|
30
30
|
sudo systemctl restart sshd
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: opswalrus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.50
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Ellis
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-09-
|
|
11
|
+
date: 2023-09-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: binding_of_caller
|
|
@@ -184,8 +184,9 @@ files:
|
|
|
184
184
|
- build.ops
|
|
185
185
|
- exe/ops
|
|
186
186
|
- lib/opswalrus.rb
|
|
187
|
+
- lib/opswalrus/_bootstrap.ops
|
|
188
|
+
- lib/opswalrus/_shell.ops
|
|
187
189
|
- lib/opswalrus/app.rb
|
|
188
|
-
- lib/opswalrus/bootstrap.ops
|
|
189
190
|
- lib/opswalrus/bootstrap.sh
|
|
190
191
|
- lib/opswalrus/bundler.rb
|
|
191
192
|
- lib/opswalrus/cli.rb
|
|
File without changes
|