opswalrus 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 727948ba554b3da5510261c8ddc8983a8113b7df7c30fb769a2291bc0af77195
4
- data.tar.gz: 70a553c15a613d41300775b0f063cb2c34fcc9998d2f8d26d310a1c88fec3a17
3
+ metadata.gz: c6a371b7cd41b84c0ea93f89180204ea580b2a8d20c9d8686639663e6bf31379
4
+ data.tar.gz: b27a653685068ba101cb89990a3fcd74b4eab39337f9592f35b9cc41f0014a48
5
5
  SHA512:
6
- metadata.gz: d1d4198f362160b5d0f1baba4fe0999f382b3cf1250cd8a608859901e55bb8f307673761c6699f60c81a70814d8eec3a67b66de241e94f95856dbdf69f703dc2
7
- data.tar.gz: 3fd8074d05b9c50976ef81a700fe95217046e7e7ced70799e6f65eac46b5d61f14f1ee267191e64264663a4d11bb3b61d202d4eab32c80e08e92b0d9769ca7ff
6
+ metadata.gz: 5928f1f07bc4ddd13f630c3967a73a196ec21999cbc1cf5d30247bd24dbec940c7fe207ff37520158b787ef635a70b41add3c6f3614d1000881ddda509361f3d
7
+ data.tar.gz: e89db2ddc7e4b97dfcd2df4e01d2a525e0a5a8757283d1de2f136c8dd3fa64a4f04aa6daaf1efe81d812c622dc2572df996b19aa66dcb9cf664826b4c38a82b9
data/Gemfile.lock CHANGED
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- opswalrus (1.0.4)
5
- bcrypt_pbkdf
6
- citrus
7
- ed25519
8
- git
9
- gli
10
- rubyzip
11
- sshkit
4
+ opswalrus (1.0.6)
5
+ bcrypt_pbkdf (~> 1.1)
6
+ citrus (~> 3.0)
7
+ ed25519 (~> 1.3)
8
+ git (~> 1.18)
9
+ gli (~> 2.21)
10
+ rubyzip (~> 2.3)
11
+ sshkit (~> 1.21)
12
12
 
13
13
  GEM
14
14
  remote: https://rubygems.org/
data/build.ops ADDED
@@ -0,0 +1,20 @@
1
+ params:
2
+ version: string
3
+
4
+ imports:
5
+ core: "https://github.com/opswalrus/core.git"
6
+ ...
7
+
8
+ version = params.version
9
+
10
+ template = <<TEMPLATE
11
+ module OpsWalrus
12
+ VERSION = "{{ version }}"
13
+ end
14
+ TEMPLATE
15
+
16
+ puts "Write version.rb for version #{version}"
17
+ core.template.write(path: "./lib/opswalrus/version.rb", template: template, variables: {version: version})
18
+
19
+ sh("Build gem") { 'gem build opswalrus.gemspec' }
20
+ sh("Build docker image") { 'docker build -t opswalrus/ops:{{ version }} .' }
data/lib/opswalrus/app.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require "citrus"
2
- require "git"
3
2
  require "io/console"
4
3
  require "json"
5
4
  require "random/formatter"
@@ -8,6 +7,7 @@ require "socket"
8
7
  require "stringio"
9
8
  require "yaml"
10
9
  require "pathname"
10
+ require_relative "git"
11
11
  require_relative "host"
12
12
  require_relative "hosts_file"
13
13
  require_relative "operation_runner"
@@ -158,24 +158,11 @@ module OpsWalrus
158
158
  ops_file = OpsFile.new(self, ops_file_path)
159
159
 
160
160
  # if the ops file is part of a package, then set the package directory as the app's pwd
161
- # puts "run1: #{ops_file.ops_file_path}"
162
161
  if ops_file.package_file && ops_file.package_file.dirname.to_s !~ /#{Bundler::BUNDLE_DIR}/
163
- # puts "set pwd: #{ops_file.package_file.dirname}"
164
- set_pwd(ops_file.package_file.dirname)
165
- rebased_ops_file_relative_path = ops_file.ops_file_path.relative_path_from(ops_file.package_file.dirname)
166
- # note: rebased_ops_file_relative_path is a relative path that is relative to ops_file.package_file.dirname
167
- # puts "rebased path: #{rebased_ops_file_relative_path}"
168
- absolute_ops_file_path = ops_file.package_file.dirname.join(rebased_ops_file_relative_path)
169
- # puts "absolute path: #{absolute_ops_file_path}"
170
- ops_file = OpsFile.new(self, absolute_ops_file_path)
162
+ ops_file = set_pwd_to_ops_file_package_directory(ops_file)
171
163
  end
172
- # puts "run2: #{ops_file.ops_file_path}"
173
164
 
174
165
  op = OperationRunner.new(self, ops_file)
175
- # if op.requires_sudo?
176
- # prompt_sudo_password unless sudo_password
177
- # end
178
- # exit_status, out, err, script_output_structure = op.run(operation_kv_args, params_json_hash: @params, verbose: @verbose)
179
166
  result = op.run(operation_kv_args, params_json_hash: @params, verbose: @verbose)
180
167
  exit_status = result.exit_status
181
168
 
@@ -183,14 +170,7 @@ module OpsWalrus
183
170
  puts "Op exit_status"
184
171
  puts exit_status
185
172
 
186
- # puts "Op stdout"
187
- # puts out
188
-
189
- # puts "Op stderr"
190
- # puts err
191
-
192
173
  puts "Op output"
193
- # puts script_output_structure ? JSON.pretty_generate(script_output_structure) : nil.inspect
194
174
  puts JSON.pretty_generate(result.value)
195
175
  end
196
176
 
@@ -203,6 +183,19 @@ module OpsWalrus
203
183
  FileUtils.remove_entry(tmp_dir) if tmp_dir
204
184
  end
205
185
 
186
+ # sets the App's pwd to the ops file's package directory and
187
+ # returns a new OpsFile that points at the revised pathname with considered as relative to the package file's directory
188
+ def set_pwd_to_ops_file_package_directory(ops_file)
189
+ # puts "set pwd: #{ops_file.package_file.dirname}"
190
+ set_pwd(ops_file.package_file.dirname)
191
+ rebased_ops_file_relative_path = ops_file.ops_file_path.relative_path_from(ops_file.package_file.dirname)
192
+ # note: rebased_ops_file_relative_path is a relative path that is relative to ops_file.package_file.dirname
193
+ # puts "rebased path: #{rebased_ops_file_relative_path}"
194
+ absolute_ops_file_path = ops_file.package_file.dirname.join(rebased_ops_file_relative_path)
195
+ # puts "absolute path: #{absolute_ops_file_path}"
196
+ OpsFile.new(self, absolute_ops_file_path)
197
+ end
198
+
206
199
  # package_operation_and_args can take one of the following forms:
207
200
  # - ["github.com/davidkellis/my-package", "operation1", "arg1:val1", "arg2:val2", "arg3:val3"]
208
201
  # - ["foo.zip", "foo/myfile.ops", "arg1:val1", "arg2:val2", "arg3:val3"]
@@ -244,7 +237,7 @@ module OpsWalrus
244
237
 
245
238
  # operation_kv_args = package_operation_and_args
246
239
  [ops_file_path, operation_kv_args, tmp_dir]
247
- when repo_url = git_repo?(package_or_ops_file_reference)
240
+ when repo_url = Git.repo?(package_or_ops_file_reference)
248
241
  destination_package_path = bundler.download_git_package(repo_url)
249
242
 
250
243
  ops_file_path, operation_kv_args = find_entry_point_ops_file_in_dir(destination_package_path, package_operation_and_args)
@@ -301,22 +294,6 @@ module OpsWalrus
301
294
  [ops_file_path, operation_kv_args]
302
295
  end
303
296
 
304
- # git_repo?("davidkellis/arborist") -> "https://github.com/davidkellis/arborist"
305
- # returns the repo URL
306
- def git_repo?(repo_reference)
307
- candidate_repo_references = [
308
- repo_reference,
309
- repo_reference =~ /(\.(com|net|org|dev|io|local))\// && "https://#{repo_reference}",
310
- repo_reference !~ /github\.com\// && repo_reference =~ /^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}\/([\w\.@\:\-~]+)$/i && "https://github.com/#{repo_reference}" # this regex is from https://www.npmjs.com/package/github-username-regex and https://www.debuggex.com/r/H4kRw1G0YPyBFjfm
311
- ].compact
312
- working_repo_reference = candidate_repo_references.find {|reference| Git.ls_remote(reference) rescue nil }
313
- working_repo_reference
314
- end
315
-
316
- # def is_dir_git_repo?(dir_path)
317
- # Git.ls_remote(reference) rescue nil
318
- # end
319
-
320
297
  def bundle_status
321
298
  end
322
299
 
@@ -22,8 +22,8 @@ module OpsWalrus
22
22
  @bundle_dir
23
23
  end
24
24
 
25
- def ensure_package_bundle_directory_exists
26
- FileUtils.mkdir_p(@bundle_dir)
25
+ def ensure_pwd_bundle_directory_exists
26
+ FileUtils.mkdir_p(@bundle_dir) unless @bundle_dir.exist?
27
27
  end
28
28
 
29
29
  # # returns the OpsFile within the bundle directory that represents the given ops_file (which is outside of the bundle directory)
@@ -50,7 +50,7 @@ module OpsWalrus
50
50
  # end
51
51
 
52
52
  def update
53
- ensure_package_bundle_directory_exists
53
+ ensure_pwd_bundle_directory_exists
54
54
 
55
55
  package_yaml_files = pwd.glob("./**/package.yaml") - pwd.glob("./**/#{BUNDLE_DIR}/**/package.yaml")
56
56
  package_files_within_pwd = package_yaml_files.map {|path| PackageFile.new(path.realpath) }
@@ -83,7 +83,7 @@ module OpsWalrus
83
83
 
84
84
  # returns the self_pkg directory within the bundle directory
85
85
  # def include_directory_in_bundle_as_self_pkg(dirname = pwd)
86
- # ensure_package_bundle_directory_exists
86
+ # ensure_pwd_bundle_directory_exists
87
87
 
88
88
  # destination_package_path = @bundle_dir.join("self_pkg")
89
89
 
@@ -103,7 +103,7 @@ module OpsWalrus
103
103
  # This method downloads a package_url that is a dependency referenced in the specified package_file
104
104
  # returns the destination directory that the package was downloaded to
105
105
  def download_package(package_file, package_reference)
106
- ensure_package_bundle_directory_exists
106
+ ensure_pwd_bundle_directory_exists
107
107
 
108
108
  local_name = package_reference.local_name
109
109
  package_url = package_reference.package_uri
@@ -144,19 +144,26 @@ module OpsWalrus
144
144
  end
145
145
 
146
146
  def download_git_package(package_url, version = nil, destination_package_path = nil)
147
- destination_package_path ||= begin
148
- package_reference_dirname = sanitize_path(package_url)
149
- bundle_dir.join(package_reference_dirname)
150
- end
151
- FileUtils.remove_dir(destination_package_path) if File.exist?(destination_package_path)
147
+ ensure_pwd_bundle_directory_exists
148
+
149
+ destination_package_path ||= dynamic_package_path_for_git_package(package_url, version)
150
+
151
+ return destination_package_path if destination_package_path.exist?
152
+
152
153
  if version
153
- Git.clone(package_url, destination_package_path, branch: version, config: ['submodule.recurse=true'])
154
+ ::Git.clone(package_url, destination_package_path, branch: version, config: ['submodule.recurse=true'])
154
155
  else
155
- Git.clone(package_url, destination_package_path, config: ['submodule.recurse=true'])
156
+ ::Git.clone(package_url, destination_package_path, config: ['submodule.recurse=true'])
156
157
  end
158
+
157
159
  destination_package_path
158
160
  end
159
161
 
162
+ def dynamic_package_path_for_git_package(package_url, version = nil)
163
+ package_reference_dirname = sanitize_path(package_url)
164
+ bundle_dir.join(package_reference_dirname)
165
+ end
166
+
160
167
  def sanitize_path(path)
161
168
  # found this at https://apidock.com/rails/v5.2.3/ActiveStorage/Filename/sanitized
162
169
  path.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "�").strip.tr("\u{202E}%$|:;/\t\r\n\\", "-")
@@ -0,0 +1,22 @@
1
+ require "git"
2
+
3
+ module OpsWalrus
4
+ class Git
5
+ # repo?("davidkellis/arborist") -> "https://github.com/davidkellis/arborist"
6
+ # returns the repo URL or directory path
7
+ def self.repo?(repo_reference)
8
+ if Dir.exist?(repo_reference)
9
+ ::Git.ls_remote(repo_reference) && repo_reference rescue nil
10
+ else
11
+ candidate_repo_references = [
12
+ repo_reference,
13
+ repo_reference =~ /(\.(com|net|org|dev|io|local))\// && "https://#{repo_reference}",
14
+ repo_reference !~ /github\.com\// && repo_reference =~ /^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}\/([\w\.@\:\-~]+)$/i && "https://github.com/#{repo_reference}" # this regex is from https://www.npmjs.com/package/github-username-regex and https://www.debuggex.com/r/H4kRw1G0YPyBFjfm
15
+ ].compact
16
+ working_repo_reference = candidate_repo_references.find {|reference| ::Git.ls_remote(reference) rescue nil }
17
+ working_repo_reference
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -27,6 +27,10 @@ module OpsWalrus
27
27
  cmd = block.call if block
28
28
  cmd ||= desc_or_cmd
29
29
 
30
+ cmd = WalrusLang.render(cmd, block.binding) if block && cmd =~ /{{.*}}/
31
+
32
+ #cmd = Shellwords.escape(cmd)
33
+
30
34
  if self.alias
31
35
  print "[#{self.alias} | #{host}] "
32
36
  else
@@ -35,11 +39,8 @@ module OpsWalrus
35
39
  print "#{description}: " if description
36
40
  puts cmd
37
41
 
38
- cmd = WalrusLang.render(cmd, block.binding) if block && cmd =~ /{{.*}}/
39
42
  return unless cmd && !cmd.strip.empty?
40
43
 
41
- #cmd = Shellwords.escape(cmd)
42
-
43
44
  # puts "shell: #{cmd}"
44
45
  # puts "shell: #{cmd.inspect}"
45
46
  # puts "sudo_password: #{sudo_password}"
@@ -72,7 +72,7 @@ module OpsWalrus
72
72
  Invocation::Error.new(e)
73
73
  end
74
74
 
75
- if verbose && result.failure?
75
+ if verbose == 2 && result.failure?
76
76
  puts "Ops script error details:"
77
77
  puts "Error: #{result.value}"
78
78
  puts "Status code: #{result.exit_status}"
@@ -1,5 +1,6 @@
1
1
  require 'pathname'
2
2
  require 'yaml'
3
+ require_relative 'git'
3
4
  require_relative 'ops_file_script'
4
5
 
5
6
  module OpsWalrus
@@ -91,12 +92,16 @@ module OpsWalrus
91
92
  imports_hash.map do |local_name, yaml_import_reference|
92
93
  local_name = local_name.to_s
93
94
  import_reference = case yaml_import_reference
95
+
96
+ # when the imports line says:
97
+ # imports:
98
+ # my_package: my_package
94
99
  in String => import_str
95
100
  case
96
101
  when package_reference = package_file&.dependency(import_str) # package dependency reference
97
102
  # in this context, import_str is the local package name documented in the package's dependencies
98
103
  PackageDependencyReference.new(local_name, package_reference)
99
- when import_str.to_pathname.exist? # path reference
104
+ when import_str.to_pathname.exist? # path reference
100
105
  path = import_str.to_pathname
101
106
  case
102
107
  when path.directory?
@@ -106,13 +111,26 @@ module OpsWalrus
106
111
  else
107
112
  raise Error, "Unknown import reference: #{local_name} -> #{import_str.inspect}"
108
113
  end
114
+ when Git.repo?(import_str) # ops file has imported an ad-hoc git repo
115
+ package_uri = import_str
116
+ destination_package_path = app.bundler.dynamic_package_path_for_git_package(package_uri)
117
+ # puts "DynamicPackageImportReference: #{local_name} -> #{destination_package_path}"
118
+ DynamicPackageImportReference.new(local_name, DynamicPackageReference.new(local_name, package_uri, nil))
119
+ else
120
+ raise Error, "Unknown import reference: #{local_name}: #{yaml_import_reference.inspect}"
109
121
  end
110
- # in Hash
122
+
123
+ # when the imports line says:
124
+ # imports:
125
+ # my_package:
126
+ # url: https://...
127
+ # version: 2.1
128
+ # in Hash => package_defn
111
129
  # url = package_defn["url"]
112
130
  # version = package_defn["version"]
113
131
  # PackageReference.new(local_name, url, version&.to_s)
114
132
  else
115
- raise Error, "Unknown package reference: #{package_defn.inspect}"
133
+ raise Error, "Unknown import reference: #{local_name}: #{yaml_import_reference.inspect}"
116
134
  end
117
135
  [local_name, import_reference]
118
136
  end.to_h
@@ -205,36 +223,5 @@ module OpsWalrus
205
223
  dirname.glob("*").select(&:directory?)
206
224
  end
207
225
 
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
- def supporting_library_include_dir_and_require_lib
216
- if Dir.exist?(ops_file_helper_library_directory)
217
- [ops_file_helper_library_directory, ops_file_helper_library_basename]
218
- elsif File.exist?(ops_file_sibling_helper_library_file)
219
- [dirname, ops_file_helper_library_basename]
220
- else
221
- [nil, nil]
222
- end
223
- end
224
-
225
- def ops_file_helper_library_basename
226
- basename.sub_ext(".rb")
227
- end
228
-
229
- # "/home/david/sync/projects/ops/ops/core/host/info.ops" => "/home/david/sync/projects/ops/ops/core/host/info"
230
- def ops_file_helper_library_directory
231
- File.join(dirname, basename)
232
- end
233
-
234
- # "/home/david/sync/projects/ops/ops/core/host/info.ops" => "/home/david/sync/projects/ops/ops/core/host/info.rb"
235
- def ops_file_sibling_helper_library_file
236
- "#{ops_file_helper_library_directory}.rb"
237
- end
238
-
239
226
  end
240
227
  end
@@ -20,6 +20,9 @@ module OpsWalrus
20
20
  def [](index, *args, **kwargs, &block)
21
21
  @obj.method(:[]).call(index, *args, **kwargs, &block)
22
22
  end
23
+ def respond_to_missing?(method, *)
24
+ @obj.is_a?(Hash) && @obj.respond_to?(method)
25
+ end
23
26
  def method_missing(name, *args, **kwargs, &block)
24
27
  case @obj
25
28
  when Array
@@ -214,6 +217,9 @@ module OpsWalrus
214
217
  end
215
218
  end
216
219
 
220
+ # currently, import may only be used to import a package that is referenced in the script's package file
221
+ # I may decide to extend this to work with dynamic package references
222
+ #
217
223
  # local_package_name is the local package name defined for the package dependency that is attempting to be referenced
218
224
  def import(local_package_name)
219
225
  local_package_name = local_package_name.to_s
@@ -254,17 +260,18 @@ module OpsWalrus
254
260
  cmd = block.call if block
255
261
  cmd ||= desc_or_cmd
256
262
 
263
+ cmd = WalrusLang.render(cmd, block.binding) if block && cmd =~ /{{.*}}/
264
+
265
+ #cmd = Shellwords.escape(cmd)
266
+
257
267
  # puts "shell! self: #{self.inspect}"
258
268
 
259
269
  print "[#{@runtime_env.local_hostname}] "
260
270
  print "#{description}: " if description
261
271
  puts cmd
262
272
 
263
- cmd = WalrusLang.render(cmd, block.binding) if block && cmd =~ /{{.*}}/
264
273
  return unless cmd && !cmd.strip.empty?
265
274
 
266
- #cmd = Shellwords.escape(cmd)
267
-
268
275
  sudo_password = @runtime_env.sudo_password
269
276
  sudo_password &&= sudo_password.gsub(/\n+$/,'') # remove trailing newlines from sudo_password
270
277
 
@@ -5,6 +5,7 @@ require_relative 'bundler'
5
5
 
6
6
  module OpsWalrus
7
7
 
8
+ # these are static package references defined ahead of time in the package file
8
9
  class PackageReference
9
10
  attr_accessor :local_name
10
11
  attr_accessor :package_uri
@@ -23,7 +24,7 @@ module OpsWalrus
23
24
  path.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "�").strip.tr("\u{202E}%$|:;/\t\r\n\\", "-")
24
25
  end
25
26
 
26
- # important: the dirname implemented as the local_name is critical because Bundler#download_package downloads
27
+ # important: the import_resolution_dirname implemented as the local_name is critical because Bundler#download_package downloads
27
28
  # package dependencies to the name that this method returns, which must match the package reference's local name
28
29
  # so that later, when the package is being looked up on the load path (in LoadPath#resolve_import_reference),
29
30
  # the package reference's referenced git repo or file path may not exist or be available, and so the package
@@ -32,12 +33,20 @@ module OpsWalrus
32
33
  # If this implementation changes, then Bundler#download_package and LoadPath#resolve_import_reference must also
33
34
  # change in order for the three things to reconcile with respect to one another, since all three bits of logic are
34
35
  # what make bundling package dependencies and loading them function properly.
35
- def dirname
36
+ def import_resolution_dirname
36
37
  local_name
37
38
  end
38
39
 
39
40
  end
40
41
 
42
+ # these are dynamic package references defined at runtime when an OpsFile's imports are being evaluated.
43
+ # this will usually be the case when an ops file does not belong to a package
44
+ class DynamicPackageReference < PackageReference
45
+ def import_resolution_dirname
46
+ sanitized_package_uri
47
+ end
48
+ end
49
+
41
50
  class PackageFile
42
51
  attr_accessor :package_file_path
43
52
  attr_accessor :yaml
@@ -32,6 +32,14 @@ module OpsWalrus
32
32
  end
33
33
  end
34
34
 
35
+ class DynamicPackageImportReference < ImportReference
36
+ attr_accessor :package_reference
37
+ def initialize(local_name, package_reference)
38
+ super(local_name)
39
+ @package_reference = package_reference
40
+ end
41
+ end
42
+
35
43
  class OpsFileReference < ImportReference
36
44
  attr_accessor :ops_file_path
37
45
  def initialize(local_name, ops_file_path)
@@ -86,6 +94,8 @@ module OpsWalrus
86
94
  @dir = dir
87
95
  @root_namespace = build_symbol_resolution_tree(@dir)
88
96
  @path_map = build_path_map(@root_namespace)
97
+
98
+ @dynamic_package_additions_memo = {}
89
99
  end
90
100
 
91
101
  # returns a tree of Namespace -> {Namespace* -> {Namespace* -> ..., OpsFile*}, OpsFile*}
@@ -129,6 +139,19 @@ module OpsWalrus
129
139
  path_map
130
140
  end
131
141
 
142
+ def dynamically_add_new_package_dir(new_package_dir)
143
+ # patch the symbol resolution (namespace) tree
144
+ dir_basename = new_package_dir.basename
145
+ unless @root_namespace.resolve_symbol(dir_basename)
146
+ new_child_namespace = build_symbol_resolution_tree(new_package_dir)
147
+ @root_namespace.add(dir_basename, new_child_namespace)
148
+
149
+ # patch the path map
150
+ new_partial_path_map = build_path_map(new_child_namespace)
151
+ @path_map.merge!(new_partial_path_map)
152
+ end
153
+ end
154
+
132
155
  # returns a Namespace
133
156
  def lookup_namespace(ops_file)
134
157
  @path_map[ops_file.dirname]
@@ -144,7 +167,16 @@ module OpsWalrus
144
167
  case import_reference
145
168
  when PackageDependencyReference
146
169
  # puts "root namespace: #{@root_namespace.symbol_table}"
147
- @root_namespace.resolve_symbol(import_reference.package_reference.local_name) # returns the Namespace associated with the bundled package dirname (i.e. the local name)
170
+ @root_namespace.resolve_symbol(import_reference.package_reference.import_resolution_dirname) # returns the Namespace associated with the bundled package dirname (i.e. the local name)
171
+ when DynamicPackageImportReference
172
+ dynamic_package_reference = import_reference.package_reference
173
+ @dynamic_package_additions_memo[dynamic_package_reference] ||= begin
174
+ # puts "Downloading dynamic package: #{dynamic_package_reference.inspect}"
175
+ dynamically_added_package_dir = @runtime_env.app.bundler.download_git_package(dynamic_package_reference.package_uri, dynamic_package_reference.version)
176
+ dynamically_add_new_package_dir(dynamically_added_package_dir)
177
+ dynamically_added_package_dir
178
+ end
179
+ @root_namespace.resolve_symbol(import_reference.package_reference.import_resolution_dirname) # returns the Namespace associated with the bundled package dirname (i.e. the sanitized package uri)
148
180
  when DirectoryReference
149
181
  @path_map[import_reference.dirname]
150
182
  when OpsFileReference
@@ -244,7 +276,7 @@ module OpsWalrus
244
276
  case import_reference
245
277
 
246
278
  # we know we're dealing with a package dependency reference, so we want to do the lookup in the bundle load path, where package dependencies live
247
- when PackageDependencyReference
279
+ when PackageDependencyReference, DynamicPackageImportReference
248
280
  @bundle_load_path.resolve_import_reference(origin_ops_file, import_reference)
249
281
 
250
282
  # we know we're dealing with a directory reference or OpsFile reference outside of the bundle dir, so we want to do the lookup in the app load path
@@ -1,3 +1,3 @@
1
1
  module OpsWalrus
2
- VERSION = "1.0.5"
2
+ VERSION = "1.0.6"
3
3
  end
@@ -57,7 +57,7 @@ module WalrusLang
57
57
 
58
58
  # binding_obj : Binding | Hash
59
59
  def self.render(template, binding_obj)
60
- binding_obj = binding_obj.to_binding if binding_obj.is_a?(Hash)
60
+ binding_obj = binding_obj.to_binding if binding_obj.respond_to?(:to_binding)
61
61
  ast = WalrusLang::Parser.parse(template)
62
62
  ast.render(binding_obj)
63
63
  end
data/opswalrus.gemspec CHANGED
@@ -11,10 +11,10 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = "opswalrus is a tool that runs scripts against a fleet of hosts"
12
12
  spec.description = "opswalrus is a tool that runs scripts against a fleet of hosts hosts. It's kind of like Ansible, but aims to be simpler to use."
13
13
  spec.homepage = "https://github.com/opswalrus/opswalrus"
14
- spec.license = 'EPL-2.0'
14
+ spec.license = "EPL-2.0"
15
15
  spec.required_ruby_version = ">= 2.6.0"
16
16
 
17
- # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
17
+ # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server - https://example.com"
18
18
 
19
19
  spec.metadata["homepage_uri"] = spec.homepage
20
20
  spec.metadata["source_code_uri"] = "https://github.com/opswalrus/opswalrus"
@@ -33,13 +33,13 @@ Gem::Specification.new do |spec|
33
33
 
34
34
  # gem dependencies
35
35
  spec.add_dependency "citrus", "~> 3.0"
36
- spec.add_dependency "gli", '~> 2.21'
37
- spec.add_dependency "git", '~> 1.18'
38
- spec.add_dependency "rubyzip", '~> 2.3'
36
+ spec.add_dependency "gli", "~> 2.21"
37
+ spec.add_dependency "git", "~> 1.18"
38
+ spec.add_dependency "rubyzip", "~> 2.3"
39
39
 
40
- spec.add_dependency "bcrypt_pbkdf", '~> 1.1'
41
- spec.add_dependency "ed25519", '~> 1.3'
42
- spec.add_dependency "sshkit", '~> 1.21'
40
+ spec.add_dependency "bcrypt_pbkdf", "~> 1.1"
41
+ spec.add_dependency "ed25519", "~> 1.3"
42
+ spec.add_dependency "sshkit", "~> 1.21"
43
43
 
44
44
  # For more information and examples about making a new gem, check out our
45
45
  # guide at: https://bundler.io/guides/creating_gem.html
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.5
4
+ version: 1.0.6
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-08-16 00:00:00.000000000 Z
11
+ date: 2023-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: citrus
@@ -124,15 +124,14 @@ files:
124
124
  - LICENSE
125
125
  - README.md
126
126
  - Rakefile
127
+ - build.ops
127
128
  - exe/ops
128
129
  - lib/opswalrus.rb
129
130
  - lib/opswalrus/app.rb
130
131
  - lib/opswalrus/bootstrap.sh
131
- - lib/opswalrus/bootstrap_linux_host1.sh
132
- - lib/opswalrus/bootstrap_linux_host2.sh
133
- - lib/opswalrus/bootstrap_linux_host3.sh
134
132
  - lib/opswalrus/bundler.rb
135
133
  - lib/opswalrus/cli.rb
134
+ - lib/opswalrus/git.rb
136
135
  - lib/opswalrus/host.rb
137
136
  - lib/opswalrus/hosts_file.rb
138
137
  - lib/opswalrus/interaction_handlers.rb
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # update package list
4
- sudo apt update -y
5
-
6
- # update OS
7
- # sudo DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-confdef" dist-upgrade -q -y --allow-downgrades --allow-remove-essential --allow-change-held-packages
8
-
9
- if [ -f /var/run/reboot-required ]; then
10
- echo 'A system reboot is required!'
11
- sudo reboot
12
- fi
@@ -1,37 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # there are probably some services that need restarting because they're using old libraries, so we'll just do the easy thing and reboot
4
- sudo DEBIAN_FRONTEND=noninteractive apt install -yq needrestart
5
-
6
- # install basic development tools
7
- sudo DEBIAN_FRONTEND=noninteractive apt install -yq build-essential
8
-
9
- # install ruby dependencies
10
- sudo DEBIAN_FRONTEND=noninteractive apt install -yq autoconf patch rustc libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev libdb-dev uuid-dev
11
-
12
- # restart services that need it
13
- sudo needrestart -q -r a
14
-
15
- # vagrant@ubuntu-jammy:~$ sudo needrestart -q -r a
16
- # systemctl restart unattended-upgrades.service
17
-
18
- # vagrant@ubuntu-jammy:~$ sudo needrestart -r l
19
- # Scanning processes...
20
- # Scanning candidates...
21
- # Scanning linux images...
22
- #
23
- # Running kernel seems to be up-to-date.
24
- #
25
- # Services to be restarted:
26
- #
27
- # Service restarts being deferred:
28
- # systemctl restart unattended-upgrades.service
29
- #
30
- # No containers need to be restarted.
31
- #
32
- # No user sessions are running outdated binaries.
33
- #
34
- # No VM guests are running outdated hypervisor (qemu) binaries on this host.
35
-
36
- # reboot just in case
37
- # sudo reboot
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # install homebrew
4
- NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
5
- eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
6
-
7
- # install gcc, rust, ruby
8
- brew install gcc
9
- brew install rust
10
- brew install ruby
11
-
12
- # brew install rtx
13
- # eval "$(rtx activate bash)" # register a shell hook
14
- # rtx use -g ruby@3.2 # install ruby via rtx
15
-
16
- # download frum for ruby version management
17
- # curl -L -o frum.tar.gz https://github.com/TaKO8Ki/frum/releases/download/v0.1.2/frum-v0.1.2-x86_64-unknown-linux-musl.tar.gz
18
- # tar -zxf frum.tar.gz
19
- # mv frum-v0.1.2-x86_64-unknown-linux-musl/frum ~/bin
20
- # chmod 755 ~/bin/frum
21
-