opswalrus 1.0.33 → 1.0.35

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: 030db97da3b6d068117676d69923976f0813583cb95a8e5a7e7d9eb500992a33
4
- data.tar.gz: dd14df25bd90ac123ad064d10ed3d32a18079766d74e97344c9c0998263a3669
3
+ metadata.gz: afddda8670c4bf29ab120d6f80d89f13d6eaa1764f4068fa8fd9cd33b4e6a4a9
4
+ data.tar.gz: eeac298ab64e7f77e5e589288fe4a69397d7a321ef3887ac378f25aa3060ffee
5
5
  SHA512:
6
- metadata.gz: fa3ca11fec12097b0deb614829f4e5919c9e64b8ccf8602d0f4faa3969105cc1768129d839120a81a88dff1242e4106951d059782f500bef1a59689ea90a5d0d
7
- data.tar.gz: b93688cb0fdd43b19581b5bae68e113aea68e67e6ccfd62704d05d868a250fb6224b36d39aeda2c06a467d6a1900967f2c7c4b095fa6a40b01a1c52d10017955
6
+ metadata.gz: f904e63bcef6b3eb970bb3ef162186268f6e95371655cab071dcb8a7c0a1c655c1f7ade92be63fe387b676d4af80e2de985909ce7a8a1e6f0a032475041eb4f4
7
+ data.tar.gz: c2d9efb14e0d063d5861e7cafa2a3a44fbeed4ca07a8e748928bfdf16cdf46dda9aabb08f3f5e259e6fbfc5a5d11ffa2254da58140fbfb40e2146214c8df27ec
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- opswalrus (1.0.33)
4
+ opswalrus (1.0.35)
5
5
  amazing_print (~> 1.5)
6
6
  bcrypt_pbkdf (~> 1.1)
7
+ binding_of_caller (~> 1.0)
7
8
  citrus (~> 3.0)
8
9
  ed25519 (~> 1.3)
9
10
  git (~> 1.18)
@@ -21,8 +22,11 @@ GEM
21
22
  public_suffix (>= 2.0.2, < 6.0)
22
23
  amazing_print (1.5.0)
23
24
  bcrypt_pbkdf (1.1.0)
25
+ binding_of_caller (1.0.0)
26
+ debug_inspector (>= 0.0.1)
24
27
  citrus (3.0.2)
25
28
  concurrent-ruby (1.2.2)
29
+ debug_inspector (1.1.0)
26
30
  diff-lcs (1.5.0)
27
31
  ed25519 (1.3.0)
28
32
  git (1.18.0)
data/README.md CHANGED
@@ -22,7 +22,7 @@ You have two options:
22
22
  The path to whatever directory you store your age identity files in should be used in place of `$HOME/.secrets/age` in the following shell alias:
23
23
 
24
24
  ```shell
25
- ❯ alias ops='docker run --rm -it -v $HOME/.secrets/age:/root/.secrets -e OPSWALRUS_AGE_IDS="/root/.secrets/*" -v $HOME/.ssh:/root/.ssh -v /var/run/docker.sock:/var/run/docker.sock -v ${PWD}/:/workdir ghcr.io/opswalrus/ops'
25
+ ❯ alias ops='docker run --rm -it -v $HOME/.secrets/age:/root/.secrets -e OPSWALRUS_AGE_IDS="/root/.secrets/*.priv" -v $HOME/.ssh:/root/.ssh -v /var/run/docker.sock:/var/run/docker.sock -v ${PWD}/:/workdir ghcr.io/opswalrus/ops'
26
26
 
27
27
  ❯ ops version
28
28
  1.0.13
@@ -116,6 +116,8 @@ module OpsWalrus
116
116
 
117
117
  destination_package_path = @bundle_dir.join(package_reference.import_resolution_dirname)
118
118
 
119
+ App.instance.log("Downloading #{package_reference} referenced in #{package_file.package_file_path} to #{destination_package_path}")
120
+
119
121
  # we return early here under the assumption that an already downloaded package/version combo will not
120
122
  # differ if we download it again multiple times to the same location
121
123
  if destination_package_path.exist?
data/lib/opswalrus/cli.rb CHANGED
@@ -72,7 +72,7 @@ module OpsWalrus
72
72
 
73
73
  desc 'Edit hosts in inventory'
74
74
  long_desc 'Edit the hosts in the inventory and their secrets'
75
- # arg_name 'hosts_file', :optional
75
+ # arg 'hosts_file', :optional
76
76
  c.command :edit do |edit|
77
77
  edit.action do |global_options, options, args|
78
78
  file_path = global_options[:hosts].first || HostsFile::DEFAULT_FILE_NAME
@@ -87,7 +87,7 @@ module OpsWalrus
87
87
 
88
88
  desc 'Encrypt secrets in inventory file'
89
89
  long_desc 'Encrypt secrets in inventory file'
90
- arg_name 'encrypted_host_file_path', :optional
90
+ arg 'encrypted_host_file_path', :optional
91
91
  c.command :encrypt do |encrypt|
92
92
  encrypt.action do |global_options, options, args|
93
93
  file_path = global_options[:hosts].first || HostsFile::DEFAULT_FILE_NAME
@@ -104,7 +104,7 @@ module OpsWalrus
104
104
 
105
105
  desc 'Decrypt secrets in inventory file'
106
106
  long_desc 'Decrypt secrets in inventory file'
107
- arg_name 'decrypted_host_file_path', :optional
107
+ arg 'decrypted_host_file_path', :optional
108
108
  c.command :decrypt do |decrypt|
109
109
  decrypt.action do |global_options, options, args|
110
110
  file_path = global_options[:hosts].first || HostsFile::DEFAULT_FILE_NAME
@@ -154,7 +154,7 @@ module OpsWalrus
154
154
 
155
155
  desc 'Run an operation from a package'
156
156
  long_desc 'Run the specified operation found within the specified package'
157
- arg_name 'args', :multiple
157
+ arg 'args', :multiple
158
158
  command :run do |c|
159
159
  c.flag [:u, :user], desc: "Specify the user that the operation will run as"
160
160
  c.switch :pass, desc: "Prompt for a sudo password"
@@ -124,12 +124,20 @@ module OpsWalrus
124
124
 
125
125
 
126
126
  module HostDSL
127
+ # runs the given command
127
128
  # returns the stdout from the command
128
129
  def sh(desc_or_cmd = nil, cmd = nil, input: nil, &block)
129
130
  out, err, status = *shell!(desc_or_cmd, cmd, block, input: input)
130
131
  out
131
132
  end
132
133
 
134
+ # runs the given command
135
+ # returns true if the exit status was success; false otherwise
136
+ def sh?(desc_or_cmd = nil, cmd = nil, input: nil, &block)
137
+ out, err, status = *shell!(desc_or_cmd, cmd, block, input: input)
138
+ status == 0
139
+ end
140
+
133
141
  # returns the tuple: [stdout, stderr, exit_status]
134
142
  def shell(desc_or_cmd = nil, cmd = nil, input: nil, &block)
135
143
  shell!(desc_or_cmd, cmd, block, input: input)
@@ -146,7 +154,19 @@ module OpsWalrus
146
154
  cmd = block.call if block
147
155
  cmd ||= desc_or_cmd
148
156
 
149
- cmd = WalrusLang.render(cmd, block.binding) if block && cmd =~ /{{.*}}/
157
+ cmd = if cmd =~ /{{.*}}/
158
+ if block
159
+ WalrusLang.render(cmd, block.binding)
160
+ else
161
+ offset = 3 # 3, because 1 references the stack frame corresponding to the caller of WalrusLang.eval,
162
+ # 2 references the stack frame corresponding to the caller of shell!,
163
+ # and 3 references the stack frame corresponding to teh caller of either sh/sh?/shell
164
+ WalrusLang.eval(cmd, offset)
165
+ end
166
+ else
167
+ cmd
168
+ end
169
+ # cmd = WalrusLang.render(cmd, block.binding) if block && cmd =~ /{{.*}}/
150
170
 
151
171
  #cmd = Shellwords.escape(cmd)
152
172
 
@@ -203,6 +223,14 @@ module OpsWalrus
203
223
  shell!(cmd)
204
224
  end
205
225
 
226
+ def desc(msg)
227
+ puts msg.mustache
228
+ end
229
+
230
+ def host_prop(name)
231
+ @props[name]
232
+ end
233
+
206
234
  end
207
235
 
208
236
  class Host
@@ -37,22 +37,47 @@ module OpsWalrus
37
37
  key, value = str_value.split(":", 2)
38
38
  if pre_existing_value = memo[param_name]
39
39
  memo[param_name] = if value # we're dealing with a Hash parameter value
40
- pre_existing_value.merge(key => value)
40
+ pre_existing_value.merge(key => try_convert(value))
41
41
  else # we're dealing with an Array parameter value or a scalar parameter value
42
42
  array = pre_existing_value.is_a?(Array) ? pre_existing_value : [pre_existing_value]
43
- array << str_value
43
+ array << try_convert(str_value)
44
44
  end
45
45
  else
46
46
  memo[param_name] = if value # we're dealing with a Hash parameter value
47
- {key => value}
47
+ {key => try_convert(value)}
48
48
  else # we're dealing with an Array parameter value or a scalar parameter value
49
- str_value
49
+ try_convert(str_value)
50
50
  end
51
51
  end
52
52
  memo
53
53
  end
54
54
  end
55
55
 
56
+ def try_convert(value)
57
+ case value.downcase
58
+ when 'true'
59
+ true
60
+ when 'false'
61
+ false
62
+ when /^[0-9]+$/
63
+ value.to_i
64
+ when /^[0-9]+\.[0-9]+$/
65
+ value.to_f
66
+ else
67
+ value
68
+ end
69
+ end
70
+
71
+ # def try_convert(value)
72
+ # if value.is_a? String
73
+ # JSON.parse(value)
74
+ # else
75
+ # value
76
+ # end
77
+ # rescue JSON::ParserError => e
78
+ # value
79
+ # end
80
+
56
81
  # runtime_kv_args is an Array(String) of the form: ["arg1:val1", "arg1:val2", ...]
57
82
  # params_json_hash is a Hash representation of a JSON string
58
83
  def run(runtime_kv_args, params_json_hash: nil)
@@ -55,9 +55,9 @@ module OpsWalrus
55
55
  @params[key]
56
56
  end
57
57
 
58
- def dig(*keys)
58
+ def dig(*keys, default: nil)
59
59
  # keys = keys.map {|key| key.is_a?(Integer) ? key : key.to_s }
60
- @params.dig(*keys)
60
+ @params.dig(*keys) || default
61
61
  end
62
62
 
63
63
  def method_missing(name, *args, **kwargs, &block)
@@ -141,6 +141,7 @@ module OpsWalrus
141
141
  def _invoke(runtime_env, hashlike_params)
142
142
  @runtime_env = runtime_env
143
143
  @params = InvocationParams.new(hashlike_params)
144
+ params = @params
144
145
  #{ruby_script}
145
146
  end
146
147
  INVOKE_METHOD
@@ -162,7 +162,7 @@ module OpsWalrus
162
162
 
163
163
  def exit(exit_status, message = nil)
164
164
  if message
165
- puts message
165
+ puts message.mustache(3)
166
166
  end
167
167
  result = if exit_status == 0
168
168
  Invocation::Success.new(nil)
@@ -198,21 +198,33 @@ module OpsWalrus
198
198
  # invocation_context._invoke(*args, **kwargs)
199
199
  end
200
200
 
201
- def params(*keys, default: nil)
202
- keys = keys.map(&:to_s)
203
- if keys.empty?
204
- @params
205
- else
206
- @params.dig(*keys) || default
207
- end
201
+ # def params(*keys, default: nil)
202
+ # keys = keys.map(&:to_s)
203
+ # if keys.empty?
204
+ # @params
205
+ # else
206
+ # @params.dig(*keys) || default
207
+ # end
208
+ # end
209
+
210
+ def desc(msg)
211
+ puts msg.mustache
208
212
  end
209
213
 
214
+ # runs the given command
210
215
  # returns the stdout from the command
211
216
  def sh(desc_or_cmd = nil, cmd = nil, input: nil, &block)
212
217
  out, err, status = *shell!(desc_or_cmd, cmd, block, input: input)
213
218
  out
214
219
  end
215
220
 
221
+ # runs the given command
222
+ # returns true if the exit status was success; false otherwise
223
+ def sh?(desc_or_cmd = nil, cmd = nil, input: nil, &block)
224
+ out, err, status = *shell!(desc_or_cmd, cmd, block, input: input)
225
+ status == 0
226
+ end
227
+
216
228
  # returns the tuple: [stdout, stderr, exit_status]
217
229
  def shell(desc_or_cmd = nil, cmd = nil, input: nil, &block)
218
230
  shell!(desc_or_cmd, cmd, block, input: input)
@@ -229,7 +241,20 @@ module OpsWalrus
229
241
  cmd = block.call if block
230
242
  cmd ||= desc_or_cmd
231
243
 
232
- cmd = WalrusLang.render(cmd, block.binding) if block && cmd =~ /{{.*}}/
244
+ cmd = if cmd =~ /{{.*}}/
245
+ if block
246
+ WalrusLang.render(cmd, block.binding)
247
+ else
248
+ offset = 3 # 3, because 1 references the stack frame corresponding to the caller of WalrusLang.eval,
249
+ # 2 references the stack frame corresponding to the caller of shell!,
250
+ # and 3 references the stack frame corresponding to teh caller of either sh/sh?/shell
251
+ WalrusLang.eval(cmd, offset)
252
+ end
253
+ else
254
+ cmd
255
+ end
256
+ # cmd = WalrusLang.eval(cmd) if !block && cmd =~ /{{.*}}/
257
+ # cmd = WalrusLang.render(cmd, block.binding) if block && cmd =~ /{{.*}}/
233
258
 
234
259
  #cmd = Shellwords.escape(cmd)
235
260
 
@@ -1,3 +1,3 @@
1
1
  module OpsWalrus
2
- VERSION = "1.0.33"
2
+ VERSION = "1.0.35"
3
3
  end
@@ -1,3 +1,4 @@
1
+ require "binding_of_caller"
1
2
  require "citrus"
2
3
  require "ostruct"
3
4
  require "stringio"
@@ -61,12 +62,21 @@ module WalrusLang
61
62
  ast = WalrusLang::Parser.parse(template)
62
63
  ast.render(binding_obj)
63
64
  end
65
+
66
+ def self.eval(template_string, bindings_from_stack_frame_offset = 1)
67
+ binding_from_earlier_stack_frame = binding.of_caller(bindings_from_stack_frame_offset)
68
+ template_string =~ /{{.*}}/ ? WalrusLang.render(template_string, binding_from_earlier_stack_frame) : template_string
69
+ end
64
70
  end
65
71
 
66
72
  class String
67
73
  def render_template(hash)
68
74
  WalrusLang.render(self, hash)
69
75
  end
76
+
77
+ def mustache(bindings_from_stack_frame_offset = 2)
78
+ WalrusLang.eval(self, bindings_from_stack_frame_offset)
79
+ end
70
80
  end
71
81
 
72
82
  class Hash
@@ -81,11 +91,6 @@ class Binding
81
91
  end
82
92
  end
83
93
 
84
- def mustache(&block)
85
- template_string = block.call
86
- template_string =~ /{{.*}}/ ? WalrusLang.render(template_string, block.binding) : template_string
87
- end
88
-
89
94
 
90
95
  # foo = 1
91
96
  # bar = 2
@@ -95,4 +100,11 @@ end
95
100
  # # puts m.dump
96
101
  # puts m.render(binding)
97
102
 
98
- # puts(mustache { "abc {{ 1 + 2 }} def" })
103
+ # puts("abc {{ 1 + 2 }} def".mustache)
104
+
105
+ # irb(main):096:0> a=5
106
+ # => 5
107
+ # irb(main):097:0> b=8
108
+ # => 8
109
+ # irb(main):098:0> "abc {{ a + b }} def".mustache
110
+ # => "abc 13 def"
data/opswalrus.gemspec CHANGED
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
33
33
 
34
34
  # gem dependencies
35
35
  spec.add_dependency "amazing_print", "~> 1.5"
36
+ spec.add_dependency "binding_of_caller", "~> 1.0"
36
37
  spec.add_dependency "citrus", "~> 3.0"
37
38
  spec.add_dependency "gli", "~> 2.21"
38
39
  spec.add_dependency "git", "~> 1.18"
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.33
4
+ version: 1.0.35
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-03 00:00:00.000000000 Z
11
+ date: 2023-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: amazing_print
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: binding_of_caller
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: citrus
29
43
  requirement: !ruby/object:Gem::Requirement