MuranoCLI 3.2.0.beta.9 → 3.2.1.pre.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/Rakefile +5 -0
  4. data/dockers/README.rst +7 -0
  5. data/dockers/RELEASE.rst +6 -3
  6. data/dockers/docker-test.sh +45 -17
  7. data/docs/completions/murano_completion-bash +211 -86
  8. data/lib/MrMurano/Account.rb +72 -4
  9. data/lib/MrMurano/Business.rb +163 -2
  10. data/lib/MrMurano/Commander-Entry.rb +1 -2
  11. data/lib/MrMurano/Config.rb +19 -18
  12. data/lib/MrMurano/Content.rb +26 -19
  13. data/lib/MrMurano/Gateway.rb +51 -10
  14. data/lib/MrMurano/ReCommander.rb +1 -1
  15. data/lib/MrMurano/Solution-Services.rb +80 -35
  16. data/lib/MrMurano/Solution-Users.rb +1 -0
  17. data/lib/MrMurano/SyncRoot.rb +10 -3
  18. data/lib/MrMurano/SyncUpDown-Core.rb +47 -36
  19. data/lib/MrMurano/SyncUpDown-Item.rb +46 -14
  20. data/lib/MrMurano/SyncUpDown.rb +22 -20
  21. data/lib/MrMurano/Webservice-Endpoint.rb +20 -18
  22. data/lib/MrMurano/Webservice-File.rb +63 -20
  23. data/lib/MrMurano/commands/business.rb +14 -1
  24. data/lib/MrMurano/commands/child.rb +148 -0
  25. data/lib/MrMurano/commands/devices.rb +298 -149
  26. data/lib/MrMurano/commands/element.rb +2 -1
  27. data/lib/MrMurano/commands/globals.rb +3 -0
  28. data/lib/MrMurano/commands/network.rb +152 -33
  29. data/lib/MrMurano/commands/sync.rb +2 -2
  30. data/lib/MrMurano/commands.rb +1 -0
  31. data/lib/MrMurano/verbosing.rb +13 -2
  32. data/lib/MrMurano/version.rb +1 -1
  33. data/spec/Account_spec.rb +43 -11
  34. data/spec/Content_spec.rb +5 -3
  35. data/spec/GatewayBase_spec.rb +1 -1
  36. data/spec/GatewayDevice_spec.rb +47 -8
  37. data/spec/GatewayResource_spec.rb +1 -1
  38. data/spec/GatewaySettings_spec.rb +1 -1
  39. data/spec/HttpAuthed_spec.rb +17 -3
  40. data/spec/ProjectFile_spec.rb +59 -23
  41. data/spec/Setting_spec.rb +2 -1
  42. data/spec/Solution-ServiceConfig_spec.rb +1 -1
  43. data/spec/Solution-ServiceEventHandler_spec.rb +27 -20
  44. data/spec/Solution-ServiceModules_spec.rb +7 -5
  45. data/spec/Solution-UsersRoles_spec.rb +7 -1
  46. data/spec/Solution_spec.rb +9 -1
  47. data/spec/SyncRoot_spec.rb +5 -5
  48. data/spec/SyncUpDown_spec.rb +262 -211
  49. data/spec/Verbosing_spec.rb +49 -8
  50. data/spec/Webservice-Cors_spec.rb +10 -1
  51. data/spec/Webservice-Endpoint_spec.rb +84 -65
  52. data/spec/Webservice-File_spec.rb +16 -11
  53. data/spec/Webservice-Setting_spec.rb +7 -1
  54. data/spec/_workspace.rb +9 -0
  55. data/spec/cmd_business_spec.rb +5 -10
  56. data/spec/cmd_common.rb +67 -32
  57. data/spec/cmd_config_spec.rb +9 -14
  58. data/spec/cmd_content_spec.rb +15 -26
  59. data/spec/cmd_cors_spec.rb +9 -12
  60. data/spec/cmd_device_spec.rb +31 -45
  61. data/spec/cmd_domain_spec.rb +12 -10
  62. data/spec/cmd_element_spec.rb +18 -17
  63. data/spec/cmd_exchange_spec.rb +1 -4
  64. data/spec/cmd_init_spec.rb +56 -72
  65. data/spec/cmd_keystore_spec.rb +17 -26
  66. data/spec/cmd_link_spec.rb +13 -17
  67. data/spec/cmd_password_spec.rb +9 -10
  68. data/spec/cmd_setting_application_spec.rb +95 -68
  69. data/spec/cmd_setting_product_spec.rb +59 -37
  70. data/spec/cmd_status_spec.rb +46 -84
  71. data/spec/cmd_syncdown_application_spec.rb +28 -50
  72. data/spec/cmd_syncdown_both_spec.rb +44 -93
  73. data/spec/cmd_syncdown_unit_spec.rb +858 -0
  74. data/spec/cmd_syncup_spec.rb +21 -56
  75. data/spec/cmd_token_spec.rb +0 -3
  76. data/spec/cmd_usage_spec.rb +15 -10
  77. data/spec/dry_run_formatter.rb +1 -0
  78. data/spec/fixtures/dumped_config +4 -4
  79. data/spec/spec_helper.rb +3 -0
  80. metadata +4 -2
@@ -9,35 +9,37 @@ require 'time'
9
9
  require 'MrMurano/Gateway'
10
10
  require 'MrMurano/ReCommander'
11
11
 
12
- command :device do |c|
13
- c.syntax = %(murano device)
14
- c.summary = %(Interact with a device)
15
- c.description = %(
16
- Interact with a device.
12
+ command :device do |cmd|
13
+ cmd.syntax = %(murano device)
14
+ cmd.summary = %(Interact with a device)
15
+ cmd.description = %(
16
+ Interact with a device.
17
17
  ).strip
18
- c.project_not_required = true
19
- c.subcmdgrouphelp = true
18
+ cmd.project_not_required = true
19
+ cmd.subcmdgrouphelp = true
20
20
 
21
- c.action do |_args, _options|
21
+ cmd.action do |_args, _options|
22
22
  ::Commander::UI.enable_paging unless $cfg['tool.no-page']
23
- say MrMurano::SubCmdGroupHelp.new(c).get_help
23
+ say MrMurano::SubCmdGroupHelp.new(cmd).get_help
24
24
  end
25
25
  end
26
26
 
27
- command 'device list' do |c|
28
- c.syntax = %(murano device list [--options])
29
- c.summary = %(List identifiers for a product)
30
- c.description = %(
31
- List identifiers for a product.
27
+ # ***
28
+
29
+ command 'device list' do |cmd|
30
+ cmd.syntax = %(murano device list [--options])
31
+ cmd.summary = %(List identifiers for a product)
32
+ cmd.description = %(
33
+ List identifiers for a product.
32
34
  ).strip
33
35
 
34
- c.option '--limit NUMBER', Integer, %(How many devices to return)
35
- c.option '--before TIMESTAMP', Integer, %(Show devices before timestamp)
36
- c.option '-l', '--long', %(show everything)
37
- c.option '-o', '--output FILE', %(Download to file instead of STDOUT)
36
+ cmd.option '--limit NUMBER', Integer, %(How many devices to return)
37
+ cmd.option '--before TIMESTAMP', Integer, %(Show devices before timestamp)
38
+ cmd.option '-l', '--long', %(show everything)
39
+ cmd.option '-o', '--output FILE', %(Download to file instead of STDOUT)
38
40
 
39
- c.action do |args, options|
40
- c.verify_arg_count!(args)
41
+ cmd.action do |args, options|
42
+ cmd.verify_arg_count!(args)
41
43
  #options.default limit: 1000
42
44
 
43
45
  prd = MrMurano::Gateway::Device.new
@@ -91,19 +93,21 @@ List identifiers for a product.
91
93
  end
92
94
  alias_command 'devices list', 'device list'
93
95
 
94
- command 'device read' do |c|
95
- c.syntax = %(murano device read <identifier> [<alias>...] [--options])
96
- c.summary = %(Read state of a device)
97
- c.description = %(
96
+ # ***
97
+
98
+ command 'device read' do |cmd|
99
+ cmd.syntax = %(murano device read <identifier> [<alias>...] [--options])
100
+ cmd.summary = %(Read state of a device)
101
+ cmd.description = %(
98
102
  Read state of a device.
99
103
 
100
104
  This reads the latest state values for the resources in a device.
101
105
  ).strip
102
106
 
103
- c.option '-o', '--output FILE', %(Download to file instead of STDOUT)
107
+ cmd.option '-o', '--output FILE', %(Download to file instead of STDOUT)
104
108
 
105
- c.action do |args, options|
106
- c.verify_arg_count!(args, nil, ['Missing device identifier'])
109
+ cmd.action do |args, options|
110
+ cmd.verify_arg_count!(args, nil, ['Missing device identifier'])
107
111
 
108
112
  prd = MrMurano::Gateway::Device.new
109
113
 
@@ -134,17 +138,19 @@ This reads the latest state values for the resources in a device.
134
138
  end
135
139
  end
136
140
 
137
- command 'device write' do |c|
138
- c.syntax = %(murano device write <identifier> <Alias=Value> [<Alias=Value>...])
139
- c.summary = %(Write to 'set' of aliases on devices)
140
- c.description = %(
141
+ # ***
142
+
143
+ command 'device write' do |cmd|
144
+ cmd.syntax = %(murano device write <identifier> <Alias=Value> [<Alias=Value>...])
145
+ cmd.summary = %(Write to 'set' of aliases on devices)
146
+ cmd.description = %(
141
147
  Write to 'set' of aliases on devices.
142
148
 
143
149
  If an alias is not settable, this will fail.
144
150
  ).strip
145
151
 
146
- c.action do |args, _options|
147
- c.verify_arg_count!(args, nil, ['Missing device identifier'])
152
+ cmd.action do |args, _options|
153
+ cmd.verify_arg_count!(args, nil, ['Missing device identifier'])
148
154
 
149
155
  resources = (MrMurano::Gateway::GweBase.new.info || {})[:resources]
150
156
 
@@ -175,117 +181,248 @@ If an alias is not settable, this will fail.
175
181
  end
176
182
  end
177
183
 
178
- command 'device enable' do |c|
179
- c.syntax = %(murano device enable (<identifier>|--file <path>) [--options])
180
- c.summary = %(Enable Identifiers in Murano for real world devices)
181
- c.description = %(
182
- Enables Identifiers, creating devices, or digital shadows, in Murano.
183
- ).strip
184
+ # ***
184
185
 
185
- c.option '-e', '--expire HOURS', %(Devices that do not activate within HOURS hours will be deleted for security purposes)
186
- c.option '-f', '--file FILE', %(A file of serial numbers, one per line)
187
- c.option '--key FILE', %(Path to file containing public TLS key for this device)
188
- allowed_types = MrMurano::Gateway::Device::DEVICE_AUTH_TYPES.map(&:to_s).sort
189
- c.option '--auth TYPE', %(Type of credential used to authenticate [#{allowed_types.join('|')}])
190
- c.option '--cred KEY', %(The credential used to authenticate, e.g., token, password, etc.)
186
+ class DeviceEnableCmd
187
+ include MrMurano::Verbose
191
188
 
192
- c.action do |args, options|
193
- c.verify_arg_count!(args, 1)
189
+ def command_init(cmd)
190
+ configure_command_meta(cmd)
191
+ configure_command_options(cmd)
192
+ configure_command_action(cmd)
193
+ end
194
194
 
195
- prd = MrMurano::Gateway::Device.new
195
+ def configure_command_meta(cmd)
196
+ cmd.syntax = %(murano device enable (<identifier>|--file <path>) [--options])
197
+ cmd.summary = %(Enable Identifiers in Murano for real world devices)
198
+ cmd.description = %(
199
+ Enable one or more Identities to create Devices, a/k/a digital twins, in Murano.
200
+ ).strip
201
+ cmd.example %(
202
+ Use a certificate request to enable a new device identity
203
+ # and obtain a TLS Client Certificate for the device to use
204
+ # to communicate with Murano.
205
+ #
206
+ # SETUP: Use the web UI to configure your Product's Public Key
207
+ # Infrastructure.
208
+ #
209
+ # Navigate to the Product Settings page, e.g.,
210
+ #
211
+ # http://localhost:4000/business/<business.id>/connectivity/<product.id>/settings
212
+ #
213
+ # Select "Enable PKI", and fill in the fields.†
214
+ #
215
+ # [†: The process of signing up with a certificate provider,
216
+ # obtaining an API key, and gererating a Client CA certificate
217
+ # is beyond the scope of this help documentation.]
218
+ #
219
+ # USAGE: You may now enable a device identify and receive a certificate.
220
+ #
221
+ # First, generate a certificate request.
222
+ #
223
+ # The following is an example of how one might use openssl to make a CSR:
224
+ #
225
+ # openssl genrsa -out rootCA.key 2048
226
+ #
227
+ # openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem
228
+ # # 1. Be sure to set the Organization Name as the same name used to the
229
+ # # Client CA Certificate.
230
+ # # 2. Set the Common Name to the name of the device identity you want to enable.
231
+ #
232
+ # openssl req -x509 -nodes -days 365 -sha256 \\
233
+ # -subj /C=/ST=/L=/O=<ORGANIZATION_NAME>/CN=<COMMON_NAME> \\
234
+ # -newkey rsa:2048 -keyout deviceIdent-key.pem
235
+ # # Be sure to set ORGANIZATION_NAME and COMMON_NAME appropriately.
236
+ #
237
+ # openssl req -new -key deviceIdent-key.pem -out deviceIdent.csr \\
238
+ # -subj "/C=/ST=/L=/O=<ORGANIZATION_NAME>/CN=<COMMON_NAME>"
239
+ # # Be sure to set ORGANIZATION_NAME and COMMON_NAME appropriately.
240
+ #
241
+ # Next, enable the device and copy the certificate.
242
+ ).lstrip, 'device_cert=$(murano device enable 12345 --expire 1 --auth csr --csr path/to/deviceIdent.csr)'
243
+ end
196
244
 
245
+ def configure_command_options(cmd)
246
+ cmd.option '-e', '--expire HOURS', %(
247
+ Devices that do not activate within HOURS hours will be deleted for security purposes
248
+ ).strip
249
+ cmd.option '-f', '--file FILE', %(A file of serial numbers, one per line)
250
+ allowed_types = MrMurano::Gateway::Device::DEVICE_AUTH_TYPES.map(&:to_s).sort
251
+ cmd.option '--auth TYPE', %(
252
+ Type of credential used to authenticate [#{allowed_types.join('|')}]
253
+ ).strip
254
+ cmd.option '--cred KEY', %(
255
+ The credential used to authenticate, e.g., token, password, etc.
256
+ ).strip
257
+ cmd.option '--key FILE', %(Path to file containing public TLS key for this device)
258
+ # (lb): --csr is identical to --key, but it's included because semantics.
259
+ cmd.option '--csr FILE', %(Path to CSR file containing certificate request)
260
+ end
261
+
262
+ def configure_command_action(cmd)
263
+ cmd.action do |args, options|
264
+ cmd.verify_arg_count!(args, 1)
265
+ must_specify_device_id_or_file!(args, options)
266
+ must_specify_auth_or_cred_maybe!(options)
267
+ must_specify_sane_expire!(options)
268
+ must_specify_valid_auth!(options)
269
+ enable_device(args, options)
270
+ end
271
+ end
272
+
273
+ def must_specify_device_id_or_file!(args, options)
197
274
  if args.count.zero? && options.file.to_s.empty?
198
- prd.error 'Missing device identifier or --file'
275
+ error 'Missing device identifier or --file'
199
276
  exit 1
200
277
  elsif !args.count.zero? && !options.file.to_s.empty?
201
- prd.error 'Please specify an identifier or --file but not both'
278
+ error 'Please specify an identifier or --file but not both'
202
279
  exit 1
203
280
  end
281
+ end
204
282
 
205
- if !options.file.nil? && (!options.key.nil? || !options.auth.nil? || !options.cred.nil?)
206
- prd.error %(Cannot use --file with any of: --key, --auth, or --cred)
283
+ def must_specify_auth_or_cred_maybe!(options)
284
+ if (
285
+ !options.file.nil? &&
286
+ (!options.key.nil? || !options.auth.nil? || !options.cred.nil?)
287
+ )
288
+ error %(Cannot use --file with any of: --key, --auth, or --cred)
207
289
  exit 1
208
290
  end
209
- if !options.key.nil? && !options.cred.nil?
210
- prd.error %(Please use either --cred or --key but not both)
291
+ credish_opts = [options.cred, options.key, options.csr]
292
+ n_credish_opts = credish_opts.count { |opt| !opt.nil? }
293
+ if n_credish_opts > 1
294
+ error %(Please use only one of: --cred, --key, or --csr)
211
295
  exit 1
212
296
  end
213
- if options.auth.nil? ^ options.cred.nil?
214
- prd.error %(Please specify both --auth and --cred or neither)
297
+ if options.auth && n_credish_opts.zero?
298
+ error %(When using --auth, please specify one of: --cred, -key, or --csr)
215
299
  exit 1
216
300
  end
217
301
  options.auth = options.auth.to_sym unless options.auth.nil?
218
- unless options.key.nil?
219
- if !options.auth.nil? && options.auth != :certificate
220
- prd.warning %(You probably mean to use "--auth certificate" with --key)
221
- else
222
- options.auth = :certificate
223
- end
302
+ return if options.key.nil?
303
+ if !options.auth.nil? && !%i[certificate csr].include?(options.auth)
304
+ warning %(You probably mean to use "--auth certificate" with --key)
224
305
  end
306
+ return if options.csr.nil? || options.auth == :csr
307
+ warning %(The --csr option is only relevant when used with "--auth csr")
308
+ end
225
309
 
226
- unless options.expire.nil?
227
- unless options.expire =~ /^[0-9]+$/
228
- prd.error %(The --expire value is not a number of hours: #{prd.fancy_ticks(options.expire)})
229
- exit 1
230
- end
231
- # The platform expects the expiration time to be an integer
232
- # representing microseconds since the epoch, e.g.,
233
- # hours * mins/hour * secs/min * msec/sec * μsec/msec
234
- # or hours * 60 * 60 * 1000 * 1000
235
- micros_since_epoch = (Time.now.to_f * 1_000_000).to_i
236
- mircos_until_purge = options.expire.to_i * 60 * 60 * 1000 * 1000
237
- options.expire = micros_since_epoch + mircos_until_purge
310
+ def must_specify_sane_expire!(options)
311
+ return if options.expire.nil?
312
+ unless options.expire =~ /^[0-9]+$/
313
+ fancy_expire = fancy_ticks(options.expire)
314
+ error %(
315
+ The --expire value is not a number of hours: #{fancy_expire}
316
+ ).strip
317
+ exit 1
238
318
  end
319
+ # The platform expects the expiration time to be an integer
320
+ # representing microseconds since the epoch, e.g.,
321
+ # hours * mins/hour * secs/min * msec/sec * μsec/msec
322
+ # or hours * 60 * 60 * 1000 * 1000
323
+ micros_since_epoch = (Time.now.to_f * 1_000_000).to_i
324
+ mircos_until_purge = options.expire.to_i * 60 * 60 * 1000 * 1000
325
+ options.expire = micros_since_epoch + mircos_until_purge
326
+ end
239
327
 
240
- unless options.auth.nil?
241
- options.auth = options.auth.to_sym
242
- unless MrMurano::Gateway::Device::DEVICE_AUTH_TYPES.include?(options.auth)
243
- MrMurano::Verbose.error("unrecognized --auth: #{options.auth}")
244
- exit 1
245
- end
246
- end
328
+ def must_specify_valid_auth!(options)
329
+ return if options.auth.nil?
330
+ options.auth = options.auth.to_sym
331
+ return if MrMurano::Gateway::Device::DEVICE_AUTH_TYPES.include?(options.auth)
332
+ MrMurano::Verbose.error("unrecognized --auth: #{options.auth}")
333
+ exit 1
334
+ end
247
335
 
336
+ def enable_device(args, options)
337
+ prd = MrMurano::Gateway::Device.new
248
338
  if !options.file.to_s.empty?
249
- # Check file for headers.
250
- begin
251
- header = File.new(options.file).gets
252
- rescue Errno::ENOENT => err
253
- prd.error %(Unable to open file #{prd.fancy_ticks(options.file)}: #{err.message})
254
- exit 2
255
- end
256
- if header.nil?
257
- prd.error 'Nothing in file!'
258
- exit 1
259
- end
260
- unless header =~ /\s*ID\s*(,SSL Client Certificate\s*)?/
261
- prd.error %(Missing column headers in file "#{options.file}")
262
- prd.error %(First line in file should be either "ID" or "ID, SSL Client Certificate")
263
- exit 2
264
- end
265
- prd.enable_batch(options.file, options.expire)
339
+ enable_device_batch(prd, options)
266
340
  elsif args.count > 0
267
- opts = {}
268
- opts[:expire] = options.expire unless options.expire.nil?
269
- opts[:type] = options.auth unless options.auth.nil?
270
- if options.key
271
- File.open(options.key, 'rb') do |io|
272
- prd.enable(args[0], **opts, key: io)
273
- end
274
- else
275
- opts[:key] = options.cred unless options.cred.nil?
276
- prd.enable(args[0], **opts)
277
- end
341
+ result = enable_device_single(prd, args[0], options)
342
+ process_enable_single_result(result, options)
278
343
  else
279
344
  # Impossible path: neither args nor --file; would've exited by now.
280
345
  raise 'Impossible'
281
346
  end
282
347
  end
348
+
349
+ def enable_device_batch(prd, options)
350
+ header = header_from_file!(options)
351
+ must_validate_header!(header, options)
352
+ prd.enable_batch(options.file, options.expire)
353
+ end
354
+
355
+ def header_from_file!(options)
356
+ # Check file for headers.
357
+ File.new(options.file).gets
358
+ rescue Errno::ENOENT => err
359
+ fancy_file = fancy_ticks(options.file)
360
+ error %(Unable to open file #{fancy_file}: #{err.message})
361
+ exit 2
362
+ end
363
+
364
+ def must_validate_header!(header, options)
365
+ if header.nil?
366
+ error 'Nothing in file!'
367
+ exit 1
368
+ end
369
+ return if header =~ /\s*ID\s*(,SSL Client Certificate\s*)?/
370
+ error %(Missing column headers in file "#{options.file}")
371
+ error %(
372
+ First line in file should be either "ID" or "ID, SSL Client Certificate"
373
+ ).strip
374
+ exit 2
375
+ end
376
+
377
+ def enable_device_single(prd, device_id, options)
378
+ enable_opts = {}
379
+ enable_opts[:expire] = options.expire unless options.expire.nil?
380
+ enable_opts[:type] = options.auth unless options.auth.nil?
381
+ enable_device_slurp_key(options, enable_opts)
382
+ prd.enable(device_id, **enable_opts)
383
+ end
384
+
385
+ def enable_device_slurp_key(options, enable_opts)
386
+ if options.key
387
+ enable_device_slurp_key_read_file(options.key, enable_opts)
388
+ elsif options.csr
389
+ enable_device_slurp_key_read_file(options.csr, enable_opts)
390
+ elsif !options.cred.nil?
391
+ enable_opts[:key] = options.cred
392
+ end
393
+ end
394
+
395
+ def enable_device_slurp_key_read_file(key_file_path, enable_opts)
396
+ File.open(key_file_path, 'rb') do |io|
397
+ enable_opts[:key] = io.read
398
+ end
399
+ end
400
+
401
+ def process_enable_single_result(result, options)
402
+ return unless options.auth == :csr
403
+ if result.to_s.empty?
404
+ warning %(Unexpected: Response missing new device identity certificate)
405
+ elsif !result.is_a?(Hash) || !result.key?(:certificate)
406
+ warning %(Unexpected: Unrecognized result format: #{result})
407
+ else
408
+ puts result[:certificate]
409
+ end
410
+ end
283
411
  end
284
412
 
285
- command 'device activate' do |c|
286
- c.syntax = %(murano device activate <identifier>)
287
- c.summary = %(Activate a serial number, retrieving its CIK)
288
- c.description = %(
413
+ def wire_cmd_device_enable
414
+ device_enable_cmd = DeviceEnableCmd.new
415
+ command('device enable') { |cmd| device_enable_cmd.command_init(cmd) }
416
+ end
417
+
418
+ wire_cmd_device_enable
419
+
420
+ # ***
421
+
422
+ command 'device activate' do |cmd|
423
+ cmd.syntax = %(murano device activate <identifier>)
424
+ cmd.summary = %(Activate a serial number, retrieving its CIK)
425
+ cmd.description = %(
289
426
  Activate an Identifier.
290
427
 
291
428
  Generally you should not use this.
@@ -300,22 +437,24 @@ Note that you can only activate a device once. After that
300
437
  you cannot retrive the CIK again.
301
438
  ).strip
302
439
 
303
- c.action do |args, _options|
304
- c.verify_arg_count!(args, nil, ['Missing device identifier'])
440
+ cmd.action do |args, _options|
441
+ cmd.verify_arg_count!(args, nil, ['Missing device identifier'])
305
442
  prd = MrMurano::Gateway::Device.new
306
443
  prd.outf prd.activate(args.first)
307
444
  end
308
445
  end
309
446
 
310
- command 'device delete' do |c|
311
- c.syntax = %(murano device delete <identifier>)
312
- c.summary = %(Delete a device)
313
- c.description = %(
314
- Delete a device.
447
+ # ***
448
+
449
+ command 'device delete' do |cmd|
450
+ cmd.syntax = %(murano device delete <identifier>)
451
+ cmd.summary = %(Delete a device)
452
+ cmd.description = %(
453
+ Delete a device.
315
454
  ).strip
316
455
 
317
- c.action do |args, _options|
318
- c.verify_arg_count!(args, nil, ['Missing device identifier'])
456
+ cmd.action do |args, _options|
457
+ cmd.verify_arg_count!(args, nil, ['Missing device identifier'])
319
458
  prd = MrMurano::Gateway::Device.new
320
459
  snid = args.shift
321
460
  ret = prd.remove(snid)
@@ -323,60 +462,68 @@ Delete a device.
323
462
  end
324
463
  end
325
464
 
326
- command 'device httpurl' do |c|
327
- c.syntax = %(murano device httpurl)
328
- c.summary = %(Get the URL for the HTTP-Data-API for this Project)
329
- c.description = %(
330
- Get the URL for the HTTP-Data-API for this Project.
465
+ # ***
466
+
467
+ command 'device httpurl' do |cmd|
468
+ cmd.syntax = %(murano device httpurl)
469
+ cmd.summary = %(Get the URL for the HTTP-Data-API for this Project)
470
+ cmd.description = %(
471
+ Get the URL for the HTTP-Data-API for this Project.
331
472
  ).strip
332
473
 
333
- c.action do |args, _options|
334
- c.verify_arg_count!(args)
474
+ cmd.action do |args, _options|
475
+ cmd.verify_arg_count!(args)
335
476
  prd = MrMurano::Gateway::GweBase.new
336
477
  ret = prd.info
337
478
  say "https://#{ret[:fqdn]}/onep:v1/stack/alias"
338
479
  end
339
480
  end
340
481
 
341
- command 'device lock' do |c|
342
- c.syntax = %(murano device lock <identifier>)
343
- c.summary = %(Lock a device, not allowing connections to it until unlocked)
344
- c.description = %(
345
- Lock a device, not allowing connections to it until unlocked.
482
+ # ***
483
+
484
+ command 'device lock' do |cmd|
485
+ cmd.syntax = %(murano device lock <identifier>)
486
+ cmd.summary = %(Lock a device, not allowing connections to it until unlocked)
487
+ cmd.description = %(
488
+ Lock a device, not allowing connections to it until unlocked.
346
489
  ).strip
347
490
 
348
- c.action do |args, _options|
349
- c.verify_arg_count!(args, 1, ['Missing device identifier'])
491
+ cmd.action do |args, _options|
492
+ cmd.verify_arg_count!(args, 1, ['Missing device identifier'])
350
493
  prd = MrMurano::Gateway::Device.new
351
494
  prd.lock(args[0])
352
495
  end
353
496
  end
354
497
 
355
- command 'device unlock' do |c|
356
- c.syntax = %(murano device unlock <identifier>)
357
- c.summary = %(Unlock a device, allowing connections to it again)
358
- c.description = %(
359
- Unlock a device, allowing connections to it again.
498
+ # ***
499
+
500
+ command 'device unlock' do |cmd|
501
+ cmd.syntax = %(murano device unlock <identifier>)
502
+ cmd.summary = %(Unlock a device, allowing connections to it again)
503
+ cmd.description = %(
504
+ Unlock a device, allowing connections to it again.
360
505
  ).strip
361
506
 
362
- c.action do |args, _options|
363
- c.verify_arg_count!(args, 1, ['Missing device identifier'])
507
+ cmd.action do |args, _options|
508
+ cmd.verify_arg_count!(args, 1, ['Missing device identifier'])
364
509
  prd = MrMurano::Gateway::Device.new
365
510
  prd.unlock(args[0])
366
511
  end
367
512
  end
368
513
 
369
- command 'device revoke' do |c|
370
- c.syntax = %(murano device revoke <identifier>)
371
- c.summary = %(Force device to reprovision)
372
- c.description = %(
514
+ # ***
515
+
516
+ command 'device revoke' do |cmd|
517
+ cmd.syntax = %(murano device revoke <identifier>)
518
+ cmd.summary = %(Force device to reprovision)
519
+ cmd.description = %(
373
520
  Force device to reprovision.
374
521
 
375
522
  This will revoke the device's keys and cause it to temporarily disconnect. The will then reconnect and be provisioned with new keys.
376
523
  ).strip
377
524
 
378
- c.action do |args, _options|
379
- c.verify_arg_count!(args, 1, ['Missing device identifier'])
525
+ cmd.action do |args, _options|
526
+ cmd.verify_arg_count!(args, 1, ['Missing device identifier'])
380
527
  prd = MrMurano::Gateway::Device.new
381
528
  # MAYBE/2017-08-23: This command doesn't return an error if the device
382
529
  # ID was not found, or if the keys were already revoked. Do we care?
@@ -385,6 +532,8 @@ This will revoke the device's keys and cause it to temporarily disconnect. The w
385
532
  end
386
533
  end
387
534
 
535
+ # ***
536
+
388
537
  alias_command 'product device', 'device'
389
538
  alias_command 'product device list', 'device list'
390
539
  alias_command 'product devices list', 'device list'