MuranoCLI 3.2.0.beta.5 → 3.2.0.beta.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.ignore +22 -11
  3. data/dockers/Dockerfile.2.2.9 +2 -2
  4. data/dockers/Dockerfile.2.3.6 +2 -2
  5. data/dockers/Dockerfile.2.4.3 +2 -2
  6. data/dockers/Dockerfile.2.5.0 +2 -2
  7. data/dockers/Dockerfile.GemRelease +6 -6
  8. data/dockers/Dockerfile.m4 +4 -4
  9. data/dockers/README.rst +87 -19
  10. data/dockers/RELEASE.rst +1 -1
  11. data/dockers/docker-test.sh +4 -1
  12. data/{.trustme.plugin → docs/ci/.trustme.plugin} +5 -2
  13. data/{.trustme.sh → docs/ci/.trustme.sh} +64 -16
  14. data/lib/MrMurano/Business.rb +73 -0
  15. data/lib/MrMurano/Config.rb +4 -3
  16. data/lib/MrMurano/Keystore.rb +4 -0
  17. data/lib/MrMurano/ReCommander.rb +23 -0
  18. data/lib/MrMurano/Solution.rb +10 -0
  19. data/lib/MrMurano/SyncUpDown-Core.rb +94 -56
  20. data/lib/MrMurano/SyncUpDown-Item.rb +2 -0
  21. data/lib/MrMurano/Webservice-Endpoint.rb +8 -7
  22. data/lib/MrMurano/commands/business.rb +60 -0
  23. data/lib/MrMurano/commands/content.rb +7 -1
  24. data/lib/MrMurano/commands/cors.rb +1 -0
  25. data/lib/MrMurano/commands/devices.rb +1 -1
  26. data/lib/MrMurano/commands/element.rb +40 -14
  27. data/lib/MrMurano/commands/keystore.rb +8 -0
  28. data/lib/MrMurano/commands/logs.rb +1 -0
  29. data/lib/MrMurano/commands/network.rb +120 -0
  30. data/lib/MrMurano/commands/postgresql.rb +2 -0
  31. data/lib/MrMurano/commands/service.rb +5 -0
  32. data/lib/MrMurano/commands/settings.rb +3 -0
  33. data/lib/MrMurano/commands/show.rb +1 -0
  34. data/lib/MrMurano/commands/status.rb +1 -0
  35. data/lib/MrMurano/commands/sync.rb +2 -0
  36. data/lib/MrMurano/commands/timeseries.rb +9 -0
  37. data/lib/MrMurano/commands/tsdb.rb +4 -0
  38. data/lib/MrMurano/commands.rb +1 -0
  39. data/lib/MrMurano/variegated/ruby_dig.rb +11 -0
  40. data/lib/MrMurano/version.rb +1 -1
  41. data/spec/cmd_element_spec.rb +2 -2
  42. data/spec/fixtures/dumped_config +1 -0
  43. metadata +6 -5
  44. /data/{.trustme.vim → docs/ci/.trustme.vim} +0 -0
@@ -8,6 +8,7 @@
8
8
  require 'optparse'
9
9
  require 'MrMurano/optparse'
10
10
  require 'MrMurano/verbosing'
11
+ require 'MrMurano/Business'
11
12
 
12
13
  module MrMurano
13
14
  class Hooked
@@ -51,6 +52,9 @@ module Commander
51
52
  attr_accessor :prompt_if_logged_off
52
53
  # A command sets subcmdgrouphelp if it's help.
53
54
  attr_accessor :subcmdgrouphelp
55
+ # A command sets must_not_be_managed if its
56
+ # use is restricted to unmanaged solutions.
57
+ attr_accessor :must_not_be_managed
54
58
 
55
59
  def verify_arg_count!(args, max_args=0, mandatory=[])
56
60
  if !max_args.nil? && max_args.zero?
@@ -84,6 +88,8 @@ module Commander
84
88
  hooked = MrMurano::Hooked.new(section)
85
89
  hooked.check_run_pre_hook
86
90
 
91
+ verify_solutions_unmanaged!
92
+
87
93
  begin
88
94
  old_run_active_command
89
95
  rescue LocalJumpError => _err
@@ -357,6 +363,23 @@ module Commander
357
363
  puts mur_msg
358
364
  exit 0
359
365
  end
366
+
367
+ # (lb): I'm not a huge fan of mingling business logic with our
368
+ # Commander monkey patch, but it's a lot more readable that
369
+ # having every command make the call!
370
+ def verify_solutions_unmanaged!
371
+ return if $cfg['tool.skip-managed']
372
+ # (lb): All @exosite.com employees are welcome behind the curtain.
373
+ if $cfg['user.name'].end_with? "@exosite.com"
374
+ MrMurano::Verbose.verbose(
375
+ "Welcome behind the curtain, #{$cfg['user.name']}!"
376
+ )
377
+ return
378
+ end
379
+ # FIXME/LATER: (lb): The Element Author should also be allowed in.
380
+ return unless active_command.must_not_be_managed
381
+ MrMurano::Business.must_not_be_managed!
382
+ end
360
383
  end
361
384
  end
362
385
 
@@ -220,6 +220,10 @@ module MrMurano
220
220
  @meta[:domain]
221
221
  end
222
222
 
223
+ def managed?
224
+ @meta[:managed]
225
+ end
226
+
223
227
  def pretty_desc(add_type: false, raw_url: false)
224
228
  # [lb] would normally put presentation code elsewhere (i.e., model
225
229
  # classes should not be formatting output), but this seems okay.
@@ -297,6 +301,12 @@ module MrMurano
297
301
  def name_validate_help
298
302
  ''
299
303
  end
304
+
305
+ def must_not_be_managed!
306
+ return unless managed?
307
+ error 'Specified command cannot be run against managed solution.'
308
+ exit 1
309
+ end
300
310
  end
301
311
 
302
312
  class Application < Solution
@@ -161,26 +161,89 @@ module MrMurano
161
161
  # @param asdown [Boolean] Direction/prespective of diff
162
162
  # @return [String] The diff output
163
163
  def dodiff(merged, local, _there=nil, options={})
164
+ localname = dodiff_resolve_localname(merged)
165
+ trmt, tlcl = dodiff_tempfile_paths(localname)
166
+ dodiff_header_aware(merged, trmt, tlcl, options)
167
+ end
168
+
169
+ def dodiff_resolve_localname(merged)
164
170
  localname = tolocalname(merged, @itemkey)
165
171
  # MUR-6488: Beware nested files, e.g., /tmp/js/script.js will
166
172
  # not work, because /tmp/js does not exist!
167
173
  # First, remove the leading path delimiter.
168
174
  localname = localname.gsub(/^#{::File::SEPARATOR}*/, '')
169
175
  # Next, replace remaining delimiters with a dot.
170
- localname = localname.tr(::File::SEPARATOR, '.')
171
- begin
172
- # (lb): Not always Lua, e.g., might be PNG. Postfix doesn't matter, though.
173
- trmt = Tempfile.new([localname + '_remote_', '.lua'])
174
- tlcl = Tempfile.new([localname + '_local_', '.lua'])
175
- rescue StandardError => err
176
- MrMurano::Verbose.error("Failed to create temporary file: #{err}")
177
- raise
176
+ localname.tr(::File::SEPARATOR, '.')
177
+ end
178
+
179
+ def dodiff_tempfile_paths(localname)
180
+ # (lb): Not always Lua, e.g., might be PNG. Postfix doesn't matter, though.
181
+ trmt = Tempfile.new([localname + '_remote_', '.lua'])
182
+ tlcl = Tempfile.new([localname + '_local_', '.lua'])
183
+ [trmt, tlcl]
184
+ rescue StandardError => err
185
+ MrMurano::Verbose.error("Failed to create temporary file: #{err}")
186
+ raise
187
+ end
188
+
189
+ def dodiff_header_aware(merged, trmt, tlcl, options)
190
+ dodiff_download_remote(merged, trmt, options)
191
+ MrMurano::Verbose.whirly_stop
192
+ dodiff_prepare_local_and_diff(merged, trmt, tlcl, options)
193
+ ensure
194
+ trmt.close
195
+ trmt.unlink
196
+ tlcl.close
197
+ tlcl.unlink
198
+ end
199
+
200
+ def dodiff_download_remote(merged, trmt, options)
201
+ tmp_path = Pathname.new(trmt.path)
202
+ diff_download(tmp_path, merged, options)
203
+ end
204
+
205
+ def dodiff_prepare_local_and_diff(merged, trmt, tlcl, options)
206
+ cmd = dodiff_build_cmd(trmt, tlcl, options)
207
+ merged[:exclude_header] = true
208
+ outp = dodiff_flexible(merged, tlcl, local, cmd, use_header=false)
209
+ return outp if outp.to_s.empty? || !merged.key?(:script)
210
+ merged[:exclude_header] = false
211
+ dodiff_diff_dynamic(merged, tlcl, local, cmd, use_header=true)
212
+ end
213
+
214
+ def dodiff_build_cmd(trmt, tlcl, options)
215
+ # 2017-07-03: No worries, Ruby 3.0 frozen string literals, cmd is a list.
216
+ cmd = $cfg['diff.cmd'].shellsplit
217
+ # ALT_SEPARATOR is the platform specific alternative separator,
218
+ # for Windows support.
219
+ remote_path = trmt.path.gsub(
220
+ ::File::SEPARATOR, ::File::ALT_SEPARATOR || ::File::SEPARATOR
221
+ )
222
+ local_path = tlcl.path.gsub(
223
+ ::File::SEPARATOR, ::File::ALT_SEPARATOR || ::File::SEPARATOR
224
+ )
225
+ if options[:asdown]
226
+ cmd << local_path
227
+ cmd << remote_path
228
+ else
229
+ cmd << remote_path
230
+ cmd << local_path
178
231
  end
232
+ cmd
233
+ end
234
+
235
+ def dodiff_flexible(merged, tlcl, local, cmd, use_header)
236
+ dodiff_local_to_tempfile(merged, tlcl, local, use_header)
237
+ dodiff_do_diff(cmd)
238
+ end
239
+
240
+ def dodiff_local_to_tempfile(merged, tlcl, local, use_header)
179
241
  Pathname.new(tlcl.path).open('wb') do |io|
180
242
  # Copy the local file to a temp file, for the diff command.
181
243
  # And for resources, remove the local-only :selected key, as
182
244
  # it's not part of the remote item that gets downloaded next.
183
245
  if merged.key?(:script)
246
+ io << config_vars_decode(merged[:header]) if use_header
184
247
  io << config_vars_decode(merged[:script])
185
248
  else
186
249
  # For most items, read the local file.
@@ -191,59 +254,34 @@ module MrMurano
191
254
  diff_item_write(io, merged, local, nil)
192
255
  end
193
256
  end
257
+ end
194
258
 
195
- stdout_and_stderr = ''
196
- begin
197
- tmp_path = Pathname.new(trmt.path)
198
- diff_download(tmp_path, merged, options)
199
-
200
- MrMurano::Verbose.whirly_stop
259
+ def dodiff_do_diff(cmd)
260
+ stdout_and_stderr, _status = Open3.capture2e(*cmd)
261
+ dodiff_cull_tempfile_paths(stdout_and_stderr)
262
+ end
201
263
 
202
- # 2017-07-03: No worries, Ruby 3.0 frozen string literals, cmd is a list.
203
- cmd = $cfg['diff.cmd'].shellsplit
204
- # ALT_SEPARATOR is the platform specific alternative separator,
205
- # for Windows support.
206
- remote_path = trmt.path.gsub(
207
- ::File::SEPARATOR, ::File::ALT_SEPARATOR || ::File::SEPARATOR
208
- )
209
- local_path = tlcl.path.gsub(
210
- ::File::SEPARATOR, ::File::ALT_SEPARATOR || ::File::SEPARATOR
211
- )
212
- if options[:asdown]
213
- cmd << local_path
214
- cmd << remote_path
264
+ def dodiff_cull_tempfile_paths(stdout_and_stderr)
265
+ # How important are the first two lines of the diff? E.g.,
266
+ # --- /tmp/raw_data_remote_20170718-20183-gdyeg9.lua 2017-07-18 ...
267
+ # +++ /tmp/raw_data_local_20170718-20183-71o4me.lua 2017-07-18 ...
268
+ # Seems like printing the path to a since-deleted temporary file is
269
+ # misleading, so cull these lines.
270
+ unless $cfg['diff.cmd'] == 'diff' || $cfg['diff.cmd'].start_with?('diff ')
271
+ return stdout_and_stderr
272
+ end
273
+ lineno = 0
274
+ consise = stdout_and_stderr.lines.reject do |line|
275
+ lineno += 1
276
+ if lineno == 1 && line.start_with?('--- ')
277
+ true
278
+ elsif lineno == 2 && line.start_with?('+++ ')
279
+ true
215
280
  else
216
- cmd << remote_path
217
- cmd << local_path
218
- end
219
-
220
- stdout_and_stderr, _status = Open3.capture2e(*cmd)
221
- # How important are the first two lines of the diff? E.g.,
222
- # --- /tmp/raw_data_remote_20170718-20183-gdyeg9.lua 2017-07-18 ...
223
- # +++ /tmp/raw_data_local_20170718-20183-71o4me.lua 2017-07-18 ...
224
- # Seems like printing the path to a since-deleted temporary file is
225
- # misleading, so cull these lines.
226
- if $cfg['diff.cmd'] == 'diff' || $cfg['diff.cmd'].start_with?('diff ')
227
- lineno = 0
228
- consise = stdout_and_stderr.lines.reject do |line|
229
- lineno += 1
230
- if lineno == 1 && line.start_with?('--- ')
231
- true
232
- elsif lineno == 2 && line.start_with?('+++ ')
233
- true
234
- else
235
- false
236
- end
237
- end
238
- stdout_and_stderr = consise.join
281
+ false
239
282
  end
240
- ensure
241
- trmt.close
242
- trmt.unlink
243
- tlcl.close
244
- tlcl.unlink
245
283
  end
246
- stdout_and_stderr
284
+ consise.join
247
285
  end
248
286
 
249
287
  ##
@@ -28,6 +28,8 @@ module MrMurano
28
28
  attr_accessor :line_beg
29
29
  # @return [Integer] The line in #local_path where this #script ends.
30
30
  attr_accessor :line_end
31
+ # @return [String] The (optional) #ITEM <method> <path> :script header.
32
+ attr_accessor :header
31
33
  # @return [String] If requested, the diff output.
32
34
  attr_accessor :diff
33
35
  # @return [Boolean] When filtering, did this item pass.
@@ -191,19 +191,20 @@ module MrMurano
191
191
  # But on murano diff, MurCLI makes two local temp files
192
192
  # to execute the diff, and it also upcases the method in
193
193
  # both files, so the diff runs clean!
194
- # VERIFY/2017-07-03: [lb] adding upcase here; hope that works!
195
- # OHOHOH/2017-07-03: [lb] also recreating the header line.
196
- up_line = "--#ENDPOINT #{md[:method].upcase} #{md[:path]}"
197
- up_line += " #{md[:ctype]}" unless md[:ctype].to_s.empty?
198
- up_line += "\n"
194
+ # 2017-07-03: (lb): Adding upcase; and recreating header.
195
+ # 2018-06-11: (lb): Added :exclude_header to deal with
196
+ # service side missing header. Which isn't an error, per se.
197
+ script_header = "--#ENDPOINT #{md[:method].upcase} #{md[:path]}"
198
+ script_header += " #{md[:ctype]}" unless md[:ctype].to_s.empty?
199
+ script_header += "\n"
199
200
  cur = RouteItem.new(
200
- #method: md[:method],
201
201
  method: md[:method].upcase,
202
202
  path: md[:path],
203
203
  content_type: (md[:ctype] || 'application/json'),
204
204
  local_path: path,
205
205
  line_beg: lineno,
206
- script: up_line,
206
+ header: script_header,
207
+ script: '',
207
208
  )
208
209
  elsif !cur.nil? && !cur[:script].nil?
209
210
  # 2017-07-02: Frozen string literal: change << to +=
@@ -99,6 +99,66 @@ command 'business list' do |c|
99
99
  c.summary = %(List businesses)
100
100
  c.description = %(
101
101
  List businesses.
102
+
103
+ E.g.,
104
+
105
+ $ murano business find my
106
+ +-------------+-------+--------------------+
107
+ | bizid | role | name |
108
+ +-------------+-------+--------------------+
109
+ | a1b2c3d4e5f | owner | My Murano Business |
110
+ +-------------+-------+--------------------+
111
+
112
+ NOTE: To match businesses that use special characters in
113
+ their name, you must either delimit or quote the string.
114
+
115
+ For example, the Bash shell interprets the pound sign as
116
+ the start of a comment, so if you were to search, e.g.,
117
+
118
+ $ murano business find #
119
+ What would you like to find?
120
+
121
+ The CLI will not receive the '#' argument, and it'll tell
122
+ you as much.
123
+
124
+ The proper way to search for such a business is to either
125
+ delimit the query, or quote it. For example,
126
+
127
+ $ murano business find "#Hashtag Business"
128
+ +-------------+-------+-------------------+
129
+ | bizid | role | name |
130
+ +-------------+-------+-------------------+
131
+ | a1b2c3d4e5f | owner | #Hashtag Business |
132
+ +-------------+-------+-------------------+
133
+
134
+ The same applies for other special characters, such as:
135
+
136
+ '&' (start process in background);
137
+ '(' and ')' (subshell invocation);
138
+ '*' (file glob);
139
+ '~' (home directory expansion);
140
+ '!' (history expansion);
141
+ '-' (ignored as an empty option).
142
+
143
+ For example, to search for a name with a parenthesis, try:
144
+
145
+ $ murano business find \\\(
146
+ +-------------+-------+---------+
147
+ | bizid | role | name |
148
+ +-------------+-------+---------+
149
+ | a1b2c3d4e5f | owner | ( ͝° ͜ʖ͡°) |
150
+ +-------------+-------+---------+
151
+
152
+ Finally to search for a business name containing a dash,
153
+ use a double-dash to indicate the end of positional
154
+ arguments. For example,
155
+
156
+ $ murano business find -- -
157
+ +-------------+-------+----------------+
158
+ | bizid | role | name |
159
+ +-------------+-------+----------------+
160
+ | a1b2c3d4e5f | owner | Loch-Busi Ness |
161
+ +-------------+-------+----------------+
102
162
  ).strip
103
163
  c.project_not_required = true
104
164
 
@@ -19,6 +19,7 @@ This is where OTA data can be stored so that devices can easily download it.
19
19
  ).strip
20
20
  c.project_not_required = true
21
21
  c.subcmdgrouphelp = true
22
+ c.must_not_be_managed = true
22
23
 
23
24
  c.action do |_args, _options|
24
25
  ::Commander::UI.enable_paging unless $cfg['tool.no-page']
@@ -35,6 +36,7 @@ List downloadable content for a product.
35
36
  Data uploaded to a product's content area can be downloaded by devices using
36
37
  the HTTP Device API.
37
38
  ).strip
39
+ c.must_not_be_managed = true
38
40
 
39
41
  c.option '-l', '--long', %(Include more info for each file)
40
42
 
@@ -50,7 +52,7 @@ the HTTP Device API.
50
52
  if !items.empty?
51
53
  prd.outf(items) do |dd, ios|
52
54
  if options.long
53
- headers = %i[Name Size 'Last Modified' MIME]
55
+ headers = %i[Name Size Last\ Modified MIME]
54
56
  rows = dd.map { |d| [d[:id], d[:length], d[:last_modified], d[:type]] }
55
57
  else
56
58
  headers = %i[Name Size]
@@ -73,6 +75,7 @@ Show more info for a content item.
73
75
  Data uploaded to a product's content area can be downloaded by devices using
74
76
  the HTTP Device API.
75
77
  ).strip
78
+ c.must_not_be_managed = true
76
79
 
77
80
  c.action do |args, _options|
78
81
  c.verify_arg_count!(args, 1, ['Missing <content name>'])
@@ -93,6 +96,7 @@ Delete a content item.
93
96
  Data uploaded to a product's content area can be downloaded by devices using
94
97
  the HTTP Device API.
95
98
  ).strip
99
+ c.must_not_be_managed = true
96
100
 
97
101
  c.option('-y', '--[no-]yes', %(Answer "yes" to all prompts and run non-interactively))
98
102
 
@@ -115,6 +119,7 @@ Upload a content item.
115
119
  Data uploaded to a product's content area can be downloaded by devices using
116
120
  the HTTP Device API.
117
121
  ).strip
122
+ c.must_not_be_managed = true
118
123
 
119
124
  c.option('--tags KEY=VALUE', %(Add extra meta info to the content item)) do |ec|
120
125
  key, value = ec.split('=', 2)
@@ -154,6 +159,7 @@ Download a content item.
154
159
  Data uploaded to a product's content area can be downloaded by devices using
155
160
  the HTTP Device API.
156
161
  ).strip
162
+ c.must_not_be_managed = true
157
163
 
158
164
  c.option '-o', '--output FILE', %(Save content to a file)
159
165
 
@@ -61,6 +61,7 @@ command 'cors set' do |c|
61
61
  Set the CORS for the project.
62
62
  ).strip
63
63
  c.project_not_required = true
64
+ c.must_not_be_managed = true
64
65
 
65
66
  c.action do |args, _options|
66
67
  c.verify_arg_count!(args, 1, ['Missing <file>'])
@@ -284,7 +284,7 @@ end
284
284
 
285
285
  command 'device activate' do |c|
286
286
  c.syntax = %(murano device activate <identifier>)
287
- c.summary = %(Activate a serial number, retriving its CIK)
287
+ c.summary = %(Activate a serial number, retrieving its CIK)
288
288
  c.description = %(
289
289
  Activate an Identifier.
290
290
 
@@ -30,9 +30,10 @@ class ElementCmd
30
30
  end
31
31
 
32
32
  def reset_state
33
+ @drop_fields = []
33
34
  @edit_fields = {}
35
+ @open_fields = []
34
36
  @updated_obj = {}
35
- @use_editor = false
36
37
  @input_path = nil
37
38
  @input_data = nil
38
39
  end
@@ -325,7 +326,11 @@ class ElementCmd
325
326
  cmd.option(
326
327
  "--#{switch} [VALUE]", detail
327
328
  ) do |param|
328
- @edit_fields[field.to_s] = param
329
+ if param.nil?
330
+ @open_fields.push(key)
331
+ else
332
+ @edit_fields[field.to_s] = param
333
+ end
329
334
  end
330
335
  end
331
336
  end
@@ -336,11 +341,19 @@ class ElementCmd
336
341
  ) do |param|
337
342
  if param.nil?
338
343
  # param.nil? means user did not supply key[=val].
339
- @edit_fields[''] = nil
344
+ @open_fields.push('')
340
345
  else
341
346
  # Otherwise: a=b :> ['a', 'b'] / a= :> ['a', ''] / a :> ['a', nil]
342
347
  key, value = param.split('=', 2)
343
- @edit_fields[key] = value
348
+ if value.nil?
349
+ if param =~ /(?<!-)-$/
350
+ @drop_fields.push(key.chomp('-'))
351
+ else
352
+ @open_fields.push(key)
353
+ end
354
+ else
355
+ @edit_fields[key] = value
356
+ end
344
357
  end
345
358
  end
346
359
  end
@@ -379,17 +392,16 @@ class ElementCmd
379
392
  if @input_path.nil?
380
393
  # See if all values are specified, or if we should bring up the EDITOR.
381
394
  if n_kvals[:n_keys] > 1
382
- if n_kvals[:n_keys] != n_kvals[:n_vals]
395
+ if (n_kvals[:n_keys] + 1) < n_kvals[:n_vals]
396
+ # EDITOR path, i.e., one key specified without a value.
383
397
  error %(
384
- Please specify at most one field when not specifing all field values.
398
+ Please specify at most one field without a value.
385
399
  ).strip
386
400
  exit 2
387
401
  end
388
- elsif n_kvals[:n_keys] == 0
402
+ elsif n_kvals[:n_keys] == 0 && @open_fields.empty?
389
403
  error('Please specify one or more -e/--edit options, or an input file.')
390
404
  exit 2
391
- else
392
- @use_editor = n_kvals[:n_vals].zero?
393
405
  end
394
406
  elsif n_kvals[:n_keys] > 1
395
407
  error('Please specify at most a single field when specifing an input file.')
@@ -423,13 +435,17 @@ class ElementCmd
423
435
  n_edits = 0
424
436
  # When @edit_fields == { '' => '' }, BizAPI replies:
425
437
  # Request Failed: 400: [400] child "type" fails because ["type" is required]
426
- if @use_editor
438
+ if !@open_fields.empty?
439
+ if (@open_fields.length > 1) && $cfg['tool.developer']
440
+ warning %(Unexpected: more than one open field specified)
441
+ end
427
442
  n_edits += update_elem_fields_from_editor
428
443
  else
429
444
  # Verify that at least one option value differs from what's currently set.
430
445
  n_edits += update_elem_fields_from_options
431
446
  n_edits += update_elem_fields_from_input_f
432
447
  end
448
+ n_edits += update_elem_fields_drop_fields
433
449
  if n_edits.zero?
434
450
  warning('No new field values specified to update.')
435
451
  exit 0
@@ -447,7 +463,7 @@ class ElementCmd
447
463
  end
448
464
 
449
465
  def prepare_field_keys_and_value
450
- field = @edit_fields.first[0]
466
+ field = @open_fields[0]
451
467
  keys = []
452
468
  keys = field.split('.').map(&:to_sym) unless field.to_s.empty?
453
469
  if !keys.nil? && !keys.empty?
@@ -535,10 +551,10 @@ class ElementCmd
535
551
  def update_elem_fields_from_input_f
536
552
  n_edits = 0
537
553
  return n_edits if @input_path.nil?
538
- if (@edit_fields.length > 1) && $cfg['tool.developer']
539
- warning %(Unexpected: more than one field specified)
554
+ if (@open_fields.length > 1) && $cfg['tool.developer']
555
+ warning %(Unexpected: more than one open field specified)
540
556
  end
541
- keys = @edit_fields.first[0].split('.').map(&:to_sym) unless @edit_fields.empty?
557
+ keys = @open_fields[0].split('.').map(&:to_sym) unless @open_fields.empty?
542
558
  if !keys.nil? && !keys.empty?
543
559
  old_val = @updated_obj.dig_safe(*keys)
544
560
  if old_val != @input_data
@@ -552,6 +568,16 @@ class ElementCmd
552
568
  n_edits
553
569
  end
554
570
 
571
+ def update_elem_fields_drop_fields
572
+ n_edits = 0
573
+ @drop_fields.each do |field|
574
+ keys = field.split('.').map(&:to_sym)
575
+ @updated_obj.deep_delete(*keys)
576
+ n_edits += 1
577
+ end
578
+ n_edits
579
+ end
580
+
555
581
  def value_specifies_file_input?(field_value)
556
582
  field_value =~ /^@(?!@)/
557
583
  end
@@ -32,6 +32,7 @@ command 'keystore clearAll' do |c|
32
32
  c.description = %(
33
33
  Delete all keys in the keystore.
34
34
  ).strip
35
+ c.must_not_be_managed = true
35
36
 
36
37
  c.action do |args, _options|
37
38
  c.verify_arg_count!(args)
@@ -46,6 +47,7 @@ command 'keystore info' do |c|
46
47
  c.description = %(
47
48
  Show info about the Keystore.
48
49
  ).strip
50
+ c.must_not_be_managed = true
49
51
 
50
52
  c.action do |args, _options|
51
53
  c.verify_arg_count!(args)
@@ -60,6 +62,7 @@ command 'keystore list' do |c|
60
62
  c.description = %(
61
63
  List all of the keys in the Keystore.
62
64
  ).strip
65
+ c.must_not_be_managed = true
63
66
 
64
67
  c.action do |args, _options|
65
68
  c.verify_arg_count!(args)
@@ -76,6 +79,7 @@ command 'keystore get' do |c|
76
79
  c.description = %(
77
80
  Get the value of a key in the Keystore.
78
81
  ).strip
82
+ c.must_not_be_managed = true
79
83
 
80
84
  c.action do |args, _options|
81
85
  c.verify_arg_count!(args, 1, ['Missing key'])
@@ -91,6 +95,7 @@ command 'keystore set' do |c|
91
95
  c.description = %(
92
96
  Set the value of a key in the Keystore.
93
97
  ).strip
98
+ c.must_not_be_managed = true
94
99
 
95
100
  c.action do |args, _options|
96
101
  c.verify_arg_count!(args, nil, ['Missing key', 'Missing value(s)'])
@@ -105,6 +110,7 @@ command 'keystore delete' do |c|
105
110
  c.description = %(
106
111
  Delete a key from the Keystore.
107
112
  ).strip
113
+ c.must_not_be_managed = true
108
114
 
109
115
  # MAYBE?/2017-08-16: Verify on delete.
110
116
  #c.option('-y', '--[no-]yes', %(Answer "yes" to all prompts and run non-interactively))
@@ -130,6 +136,8 @@ For current list, see:
130
136
 
131
137
  http://docs.exosite.com/murano/services/keystore/#command
132
138
  ).strip
139
+ c.must_not_be_managed = true
140
+
133
141
  c.example %(murano keystore command lpush mykey myvalue), %(Push a value onto list)
134
142
  c.example %(murano keystore command lpush mykey A B C), %(Push three values onto list)
135
143
  c.example %(murano keystore command lrem mykey 0 B), %(Remove all B values from list)
@@ -76,6 +76,7 @@ class LogsCmd
76
76
  def cmd_add_logs_meta(cmd)
77
77
  cmd.syntax = %(murano logs [--options])
78
78
  cmd.summary = %(Get the logs for a solution)
79
+ cmd.must_not_be_managed = true
79
80
  cmd_add_help(cmd)
80
81
  cmd_add_examples(cmd)
81
82
  end