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

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.
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