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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/Rakefile +5 -0
- data/dockers/README.rst +7 -0
- data/dockers/RELEASE.rst +6 -3
- data/dockers/docker-test.sh +45 -17
- data/docs/completions/murano_completion-bash +211 -86
- data/lib/MrMurano/Account.rb +72 -4
- data/lib/MrMurano/Business.rb +163 -2
- data/lib/MrMurano/Commander-Entry.rb +1 -2
- data/lib/MrMurano/Config.rb +19 -18
- data/lib/MrMurano/Content.rb +26 -19
- data/lib/MrMurano/Gateway.rb +51 -10
- data/lib/MrMurano/ReCommander.rb +1 -1
- data/lib/MrMurano/Solution-Services.rb +80 -35
- data/lib/MrMurano/Solution-Users.rb +1 -0
- data/lib/MrMurano/SyncRoot.rb +10 -3
- data/lib/MrMurano/SyncUpDown-Core.rb +47 -36
- data/lib/MrMurano/SyncUpDown-Item.rb +46 -14
- data/lib/MrMurano/SyncUpDown.rb +22 -20
- data/lib/MrMurano/Webservice-Endpoint.rb +20 -18
- data/lib/MrMurano/Webservice-File.rb +63 -20
- data/lib/MrMurano/commands/business.rb +14 -1
- data/lib/MrMurano/commands/child.rb +148 -0
- data/lib/MrMurano/commands/devices.rb +298 -149
- data/lib/MrMurano/commands/element.rb +2 -1
- data/lib/MrMurano/commands/globals.rb +3 -0
- data/lib/MrMurano/commands/network.rb +152 -33
- data/lib/MrMurano/commands/sync.rb +2 -2
- data/lib/MrMurano/commands.rb +1 -0
- data/lib/MrMurano/verbosing.rb +13 -2
- data/lib/MrMurano/version.rb +1 -1
- data/spec/Account_spec.rb +43 -11
- data/spec/Content_spec.rb +5 -3
- data/spec/GatewayBase_spec.rb +1 -1
- data/spec/GatewayDevice_spec.rb +47 -8
- data/spec/GatewayResource_spec.rb +1 -1
- data/spec/GatewaySettings_spec.rb +1 -1
- data/spec/HttpAuthed_spec.rb +17 -3
- data/spec/ProjectFile_spec.rb +59 -23
- data/spec/Setting_spec.rb +2 -1
- data/spec/Solution-ServiceConfig_spec.rb +1 -1
- data/spec/Solution-ServiceEventHandler_spec.rb +27 -20
- data/spec/Solution-ServiceModules_spec.rb +7 -5
- data/spec/Solution-UsersRoles_spec.rb +7 -1
- data/spec/Solution_spec.rb +9 -1
- data/spec/SyncRoot_spec.rb +5 -5
- data/spec/SyncUpDown_spec.rb +262 -211
- data/spec/Verbosing_spec.rb +49 -8
- data/spec/Webservice-Cors_spec.rb +10 -1
- data/spec/Webservice-Endpoint_spec.rb +84 -65
- data/spec/Webservice-File_spec.rb +16 -11
- data/spec/Webservice-Setting_spec.rb +7 -1
- data/spec/_workspace.rb +9 -0
- data/spec/cmd_business_spec.rb +5 -10
- data/spec/cmd_common.rb +67 -32
- data/spec/cmd_config_spec.rb +9 -14
- data/spec/cmd_content_spec.rb +15 -26
- data/spec/cmd_cors_spec.rb +9 -12
- data/spec/cmd_device_spec.rb +31 -45
- data/spec/cmd_domain_spec.rb +12 -10
- data/spec/cmd_element_spec.rb +18 -17
- data/spec/cmd_exchange_spec.rb +1 -4
- data/spec/cmd_init_spec.rb +56 -72
- data/spec/cmd_keystore_spec.rb +17 -26
- data/spec/cmd_link_spec.rb +13 -17
- data/spec/cmd_password_spec.rb +9 -10
- data/spec/cmd_setting_application_spec.rb +95 -68
- data/spec/cmd_setting_product_spec.rb +59 -37
- data/spec/cmd_status_spec.rb +46 -84
- data/spec/cmd_syncdown_application_spec.rb +28 -50
- data/spec/cmd_syncdown_both_spec.rb +44 -93
- data/spec/cmd_syncdown_unit_spec.rb +858 -0
- data/spec/cmd_syncup_spec.rb +21 -56
- data/spec/cmd_token_spec.rb +0 -3
- data/spec/cmd_usage_spec.rb +15 -10
- data/spec/dry_run_formatter.rb +1 -0
- data/spec/fixtures/dumped_config +4 -4
- data/spec/spec_helper.rb +3 -0
- 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 |
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
19
|
-
|
18
|
+
cmd.project_not_required = true
|
19
|
+
cmd.subcmdgrouphelp = true
|
20
20
|
|
21
|
-
|
21
|
+
cmd.action do |_args, _options|
|
22
22
|
::Commander::UI.enable_paging unless $cfg['tool.no-page']
|
23
|
-
say MrMurano::SubCmdGroupHelp.new(
|
23
|
+
say MrMurano::SubCmdGroupHelp.new(cmd).get_help
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
107
|
+
cmd.option '-o', '--output FILE', %(Download to file instead of STDOUT)
|
104
108
|
|
105
|
-
|
106
|
-
|
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
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
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
|
-
|
147
|
-
|
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
|
-
|
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
|
-
|
186
|
-
|
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
|
-
|
193
|
-
|
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
|
-
|
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
|
-
|
275
|
+
error 'Missing device identifier or --file'
|
199
276
|
exit 1
|
200
277
|
elsif !args.count.zero? && !options.file.to_s.empty?
|
201
|
-
|
278
|
+
error 'Please specify an identifier or --file but not both'
|
202
279
|
exit 1
|
203
280
|
end
|
281
|
+
end
|
204
282
|
|
205
|
-
|
206
|
-
|
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
|
-
|
210
|
-
|
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
|
214
|
-
|
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
|
-
|
219
|
-
|
220
|
-
|
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
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
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
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
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
|
-
|
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
|
-
|
268
|
-
|
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
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
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
|
-
|
304
|
-
|
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
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
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
|
-
|
318
|
-
|
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
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
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
|
-
|
334
|
-
|
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
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
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
|
-
|
349
|
-
|
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
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
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
|
-
|
363
|
-
|
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
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
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
|
-
|
379
|
-
|
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'
|