opswalrus 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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
-