morpheus-cli 6.3.2 → 6.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +4 -0
- data/lib/morpheus/api/backup_restores_interface.rb +4 -0
- data/lib/morpheus/api/backup_types_interface.rb +9 -0
- data/lib/morpheus/cli/cli_command.rb +4 -1
- data/lib/morpheus/cli/commands/backup_types_command.rb +53 -0
- data/lib/morpheus/cli/commands/backups_command.rb +100 -21
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +0 -26
- data/lib/morpheus/cli/commands/clouds.rb +22 -4
- data/lib/morpheus/cli/commands/curl_command.rb +1 -1
- data/lib/morpheus/cli/commands/dashboard_command.rb +2 -1
- data/lib/morpheus/cli/commands/groups.rb +50 -7
- data/lib/morpheus/cli/commands/library_forms_command.rb +1 -1
- data/lib/morpheus/cli/commands/library_option_lists_command.rb +1 -1
- data/lib/morpheus/cli/commands/library_option_types_command.rb +1 -1
- data/lib/morpheus/cli/commands/networks_command.rb +1 -1
- data/lib/morpheus/cli/commands/security_packages.rb +1 -1
- data/lib/morpheus/cli/commands/setup.rb +1 -1
- data/lib/morpheus/cli/commands/tasks.rb +2 -2
- data/lib/morpheus/cli/commands/user_settings_command.rb +10 -1
- data/lib/morpheus/cli/mixins/backups_helper.rb +4 -3
- data/lib/morpheus/cli/option_types.rb +9 -2
- data/lib/morpheus/cli/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 044ab9d85780cd6e8c58298dd7eea8c389093c0c40f97e444c1050ecb9447d65
|
4
|
+
data.tar.gz: 54d733790244eea47f2310d0211dc4173ff26a89b9cde962cc64627f1ea8a68a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 527cceb963b7b673ec478a1717cf39b0481a295a59026430944621d6e9133044e6296107d90c336750ff5413599032379e0d012285a23a63e1ecd1287558a863
|
7
|
+
data.tar.gz: a160e2dc2676bcaaded2318268f72df801b9c6514293ba6c1ce59c54cc6803221e04885066d961bdb78dbcfa49855236f79ab24727685d35442e40dda5933ad5
|
data/Dockerfile
CHANGED
@@ -894,6 +894,10 @@ class Morpheus::APIClient
|
|
894
894
|
Morpheus::BackupServiceTypesInterface.new(common_interface_options).setopts(@options)
|
895
895
|
end
|
896
896
|
|
897
|
+
def backup_types
|
898
|
+
Morpheus::BackupTypesInterface.new(common_interface_options).setopts(@options)
|
899
|
+
end
|
900
|
+
|
897
901
|
def catalog_item_types
|
898
902
|
Morpheus::CatalogItemTypesInterface.new(common_interface_options).setopts(@options)
|
899
903
|
end
|
@@ -15,6 +15,10 @@ class Morpheus::BackupRestoresInterface < Morpheus::APIClient
|
|
15
15
|
execute(method: :get, url: "#{base_path}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
|
16
16
|
end
|
17
17
|
|
18
|
+
def create(payload, params={}, headers={})
|
19
|
+
execute(method: :post, url: "#{base_path}", params: params, payload: payload, headers: headers)
|
20
|
+
end
|
21
|
+
|
18
22
|
def destroy(id, params = {}, headers={})
|
19
23
|
validate_id!(id)
|
20
24
|
execute(method: :delete, url: "#{base_path}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
|
@@ -200,6 +200,9 @@ module Morpheus
|
|
200
200
|
# value_label = 'SELECT'
|
201
201
|
# elsif option['type'] == 'select'
|
202
202
|
end
|
203
|
+
if option_type['optionalValue']
|
204
|
+
value_label = "[#{value_label}]"
|
205
|
+
end
|
203
206
|
full_option = "--#{full_field_name} #{value_label}"
|
204
207
|
# switch is an alias for the full option name, fieldName is the default
|
205
208
|
if option_type['switch']
|
@@ -563,7 +566,7 @@ module Morpheus
|
|
563
566
|
# added with :payload too... just need it here to avoid unknown key error
|
564
567
|
# todo: remove this when every command supporting :payload is updated to use parse_payload(options) and execute_api(options)
|
565
568
|
when :list
|
566
|
-
opts.on( '-m', '--max MAX', "Max Results
|
569
|
+
opts.on( '-m', '--max MAX', "Max Results" ) do |val|
|
567
570
|
# api supports max=-1 for all at the moment..
|
568
571
|
if val.to_s == "all" || val.to_s == "-1"
|
569
572
|
options[:max] = "-1"
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
|
3
|
+
class Morpheus::Cli::BackupTypes
|
4
|
+
include Morpheus::Cli::CliCommand
|
5
|
+
include Morpheus::Cli::RestCommand
|
6
|
+
|
7
|
+
set_command_description "View backup types."
|
8
|
+
set_command_name :'backup-types'
|
9
|
+
register_subcommands :list, :get
|
10
|
+
register_interfaces :backup_types
|
11
|
+
|
12
|
+
# This is a hidden command, could move to backup list-types and backup get-type
|
13
|
+
set_command_hidden
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def backup_type_list_column_definitions(options)
|
18
|
+
{
|
19
|
+
"ID" => 'id',
|
20
|
+
"Name" => 'name',
|
21
|
+
"Code" => 'code',
|
22
|
+
# "Active" => lambda {|it| format_boolean it['active'] },
|
23
|
+
# "Provider Code" => 'providerCode',
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def backup_type_column_definitions(options)
|
28
|
+
{
|
29
|
+
"ID" => 'id',
|
30
|
+
"Name" => 'name',
|
31
|
+
"Code" => 'code',
|
32
|
+
#"Backup Format" => 'backupFormat',
|
33
|
+
"Active" => lambda {|it| format_boolean it['active'] },
|
34
|
+
# "Container Type" => 'containerType',
|
35
|
+
# "Container Format" => 'containerFormat',
|
36
|
+
# "Container Category" => 'containerCategory',
|
37
|
+
"Restore Type" => 'restoreType',
|
38
|
+
# "Has Stream To Store" => lambda {|it| format_boolean it['hasStreamToStore'] },
|
39
|
+
# "Has Copy To Store" => lambda {|it| format_boolean it['hasCopyToStore'] },
|
40
|
+
"Download" => lambda {|it| format_boolean it['downloadEnabled'] },
|
41
|
+
# "Download From Store Only" => lambda {|it| format_boolean it['downloadFromStoreOnly'] },
|
42
|
+
# "Copy To Store" => lambda {|it| format_boolean it['copyToStore'] },
|
43
|
+
"Restore Existing" => lambda {|it| format_boolean it['restoreExistingEnabled'] },
|
44
|
+
"Restore New" => lambda {|it| format_boolean it['restoreNewEnabled'] },
|
45
|
+
# "Restore New Mode" => 'restoreNewMode',
|
46
|
+
# "Prune Results On Restore Existing" => lambda {|it| format_boolean it['pruneResultsOnRestoreExisting'] },
|
47
|
+
# "Restrict Targets" => lambda {|it| format_boolean it['restrictTargets'] },
|
48
|
+
# "Provider Code" => 'providerCode',
|
49
|
+
"Plugin" => lambda {|it| format_boolean it['isPlugin'] },
|
50
|
+
"Embedded" => lambda {|it| format_boolean it['isEmbedded'] },
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
@@ -9,7 +9,7 @@ class Morpheus::Cli::BackupsCommand
|
|
9
9
|
|
10
10
|
set_command_description "View and manage backups"
|
11
11
|
set_command_name :'backups'
|
12
|
-
register_subcommands :list, :get, :add, :update, :remove, :execute
|
12
|
+
register_subcommands :list, :get, :add, :update, :remove, :execute, :restore
|
13
13
|
register_subcommands :list_jobs, :get_job, :add_job, :update_job, :remove_job, :execute_job
|
14
14
|
register_subcommands :list_results, :get_result, :remove_result
|
15
15
|
register_subcommands :list_restores, :get_restore, :remove_restore
|
@@ -45,7 +45,7 @@ class Morpheus::Cli::BackupsCommand
|
|
45
45
|
end
|
46
46
|
params.merge!(parse_list_options(options))
|
47
47
|
parse_options(options, params)
|
48
|
-
execute_api(@backups_interface, :list, [], options, '
|
48
|
+
execute_api(@backups_interface, :list, [], options, 'backups') do |json_response|
|
49
49
|
backups = json_response['backups']
|
50
50
|
print_h1 "Morpheus Backups", parse_list_subtitles(options), options
|
51
51
|
if backups.empty?
|
@@ -315,19 +315,18 @@ EOT
|
|
315
315
|
end
|
316
316
|
|
317
317
|
def restore(args)
|
318
|
-
raise "Not Yet Implemented"
|
319
318
|
options = {}
|
320
319
|
params = {}
|
321
320
|
payload = {}
|
322
321
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
323
322
|
opts.banner = subcommand_usage("[backup] [result] [options]")
|
324
|
-
build_standard_post_options(opts, options)
|
323
|
+
build_standard_post_options(opts, options, [:auto_confirm])
|
325
324
|
opts.on('--result ID', String, "Backup Result ID that is being restored") do |val|
|
326
325
|
options[:options]['backupResultId'] = val
|
327
326
|
end
|
328
327
|
opts.on('--restore-instance existing|new', String, "Instance being targeted for the restore, existing to restore the current instance or new to create a new instance. The current instance is targeted by default.") do |val|
|
329
|
-
#
|
330
|
-
options[:options]['
|
328
|
+
# restoreInstance=existing|new and the flag on the restore object is called 'restoreToNew'
|
329
|
+
options[:options]['restoreInstance'] = val
|
331
330
|
end
|
332
331
|
opts.footer = <<-EOT
|
333
332
|
Restore a backup, replacing the existing target with the specified backup result.
|
@@ -350,32 +349,71 @@ EOT
|
|
350
349
|
available_backups = @backups_interface.list({max:10000})['backups'].collect {|it| {'name' => it['name'], 'value' => it['id']}}
|
351
350
|
backup_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'backupId', 'fieldLabel' => 'Backup', 'type' => 'select', 'selectOptions' => available_backups, 'required' => true}], options[:options], @api_client)['backupId']
|
352
351
|
backup = find_backup_by_name_or_id(backup_id)
|
353
|
-
|
352
|
+
return 1 if backup.nil?
|
354
353
|
end
|
355
354
|
end
|
356
355
|
# Prompt for backup result
|
357
356
|
if backup_result.nil?
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
# Name
|
363
|
-
params['name'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Backup Name'}], options[:options], @api_client)['name']
|
357
|
+
#available_backup_results = @backup_results_interface.list({backupId: backup['id'], status: ['success', 'succeeded'], max:10000})['results'].collect {|it| {format_backup_result_option_name(it), 'value' => it['id']}}
|
358
|
+
available_backup_results = @backup_results_interface.list({backupId: backup['id'], max:10000})['results'].select {|it| it['status'].to_s.downcase == 'succeeded' || it['status'].to_s.downcase == 'success' }.collect {|it| {'name' => format_backup_result_option_name(it), 'value' => it['id']} }
|
359
|
+
params['backupResultId'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'backupResultId', 'fieldLabel' => 'Backup Result', 'type' => 'select', 'selectOptions' => available_backup_results, 'required' => true}], options[:options], @api_client)['backupResultId']
|
360
|
+
backup_result = @backup_results_interface.get(params['backupResultId'].to_i)['result']
|
364
361
|
end
|
365
|
-
|
366
362
|
parse_payload(options, 'restore') do |payload|
|
367
363
|
# Prompt for restore configuration
|
368
|
-
#
|
364
|
+
# todo: These options should be based on backup type
|
365
|
+
# Look at backup_type['restoreExistingEnabled'] and backup_type['restoreNewEnabled']
|
369
366
|
# Target Instance
|
370
|
-
if backup_result['
|
371
|
-
|
367
|
+
#if backup_result['instanceId']
|
368
|
+
if backup['locationType'] == 'instance'
|
369
|
+
instance = backup['instance']
|
370
|
+
# could actually fetch the instance.., only need name and id right now though.
|
371
|
+
raise_command_error "Backup instance not found" if instance.nil?
|
372
|
+
params['restoreInstance'] = prompt_value({'fieldName' => 'restoreInstance', 'fieldLabel' => 'Restore Instance', 'type' => 'select', 'selectOptions' => [{'name' => 'Current Instance', 'value' => 'existing'}, {'name' => 'New Instance', 'value' => 'new'}], 'defaultValue' => 'existing', 'required' => true, 'description' => 'Restore the current instance or a new instance?'}, options)
|
373
|
+
if params['restoreInstance'] == 'new'
|
374
|
+
# new instance
|
375
|
+
config_map = prompt_restore_instance_config(options)
|
376
|
+
params['instanceConfig'] = config_map
|
377
|
+
else
|
378
|
+
# existing instance
|
379
|
+
# confirm the instance
|
380
|
+
keep_prompting = !options[:no_prompt]
|
381
|
+
while keep_prompting
|
382
|
+
instance_id = prompt_value({'fieldName' => 'instanceId', 'fieldLabel' => 'Confirm Instance ID', 'type' => 'text', 'required' => true, 'description' => "Enter the current instance ID to confirm that you wish to restore it."}, options)
|
383
|
+
if instance_id && instance_id.to_i == instance['id']
|
384
|
+
params['instanceId'] = instance_id.to_i
|
385
|
+
keep_prompting = false
|
386
|
+
elsif instance_id.to_s.downcase == instance['name'].to_s.downcase # allow matching on name too
|
387
|
+
params['instanceId'] = instance['id']
|
388
|
+
keep_prompting = false
|
389
|
+
else
|
390
|
+
print_red_alert "The value '#{instance_id}' does not match the existing instance #{instance['name']} [#{instance['id'] rescue ''}]. Please try again."
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
elsif backup['locationType'] == 'server'
|
395
|
+
# prompt for server type backup restore
|
396
|
+
elsif backup['locationType'] == 'storage'
|
397
|
+
# prompt for storage type backup restore
|
398
|
+
else
|
399
|
+
print yellow, "Backup location type is unknown: #{backup['locationType']}",reset,"\n"
|
372
400
|
end
|
373
|
-
|
401
|
+
|
402
|
+
payload['restore'].deep_merge!(params)
|
374
403
|
end
|
375
404
|
|
376
|
-
|
377
|
-
|
378
|
-
|
405
|
+
if params['restoreInstance'] != 'new'
|
406
|
+
if backup['instance']
|
407
|
+
print cyan,"You have selected to restore the existing instance #{backup['instance']['name'] rescue ''} [#{backup['instance']['id'] rescue ''}] with the backup result #{format_backup_result_option_name(backup_result)} [#{backup_result['id']}]",reset,"\n"
|
408
|
+
end
|
409
|
+
if backup['sourceProviderId']
|
410
|
+
print yellow,"#{bold}WARNING!#{reset}#{yellow} Restoring a backup will overwite objects when restored to an existing object store.",reset,"\n"
|
411
|
+
else
|
412
|
+
print yellow,"#{bold}WARNING!#{reset}#{yellow} Restoring a backup will erase all data when restored to an existing instance.",reset,"\n"
|
413
|
+
end
|
414
|
+
end
|
415
|
+
confirm!("Are you sure you want to restore the backup result?", options)
|
416
|
+
execute_api(@backup_restores_interface, :create, [], options, 'restore') do |json_response|
|
379
417
|
print_green_success "Restoring backup result ID: #{backup_result['id']} Name: #{backup_result['backup']['name'] rescue ''} Date: (#{format_local_dt(backup_result['dateCreated'])}"
|
380
418
|
# should get the restore maybe, or could even support refreshing until it is complete...
|
381
419
|
# restore = json_response["restore"]
|
@@ -506,4 +544,45 @@ EOT
|
|
506
544
|
]
|
507
545
|
end
|
508
546
|
|
547
|
+
def format_backup_result_option_name(result)
|
548
|
+
"#{result['backup']['name']} (#{format_local_dt(result['startDate'])})"
|
549
|
+
end
|
550
|
+
|
551
|
+
# prompt for an instance config (vdiPool.instanceConfig)
|
552
|
+
def prompt_restore_instance_config(options)
|
553
|
+
# use config if user passed one in..
|
554
|
+
scope_context = 'instanceConfig'
|
555
|
+
scoped_instance_config = {}
|
556
|
+
if options[:options][scope_context].is_a?(Hash)
|
557
|
+
scoped_instance_config = options[:options][scope_context]
|
558
|
+
end
|
559
|
+
|
560
|
+
# now configure an instance like normal, use the config as default options with :always_prompt
|
561
|
+
instance_prompt_options = {}
|
562
|
+
# instance_prompt_options[:group] = group ? group['id'] : nil
|
563
|
+
# #instance_prompt_options[:cloud] = cloud ? cloud['name'] : nil
|
564
|
+
# instance_prompt_options[:default_cloud] = cloud ? cloud['name'] : nil
|
565
|
+
# instance_prompt_options[:environment] = selected_environment ? selected_environment['code'] : nil
|
566
|
+
# instance_prompt_options[:default_security_groups] = scoped_instance_config['securityGroups'] ? scoped_instance_config['securityGroups'] : nil
|
567
|
+
|
568
|
+
instance_prompt_options[:no_prompt] = options[:no_prompt]
|
569
|
+
#instance_prompt_options[:always_prompt] = options[:no_prompt] != true # options[:always_prompt]
|
570
|
+
instance_prompt_options[:options] = scoped_instance_config
|
571
|
+
#instance_prompt_options[:options][:always_prompt] = instance_prompt_options[:no_prompt] != true
|
572
|
+
instance_prompt_options[:options][:no_prompt] = instance_prompt_options[:no_prompt]
|
573
|
+
|
574
|
+
#instance_prompt_options[:name_required] = true
|
575
|
+
# instance_prompt_options[:instance_type_code] = instance_type_code
|
576
|
+
# todo: an effort to render more useful help eg. -O Web.0.instance.name
|
577
|
+
help_field_prefix = scope_context
|
578
|
+
instance_prompt_options[:help_field_prefix] = help_field_prefix
|
579
|
+
instance_prompt_options[:options][:help_field_prefix] = help_field_prefix
|
580
|
+
# instance_prompt_options[:locked_fields] = scoped_instance_config['lockedFields']
|
581
|
+
# instance_prompt_options[:for_app] = true
|
582
|
+
instance_prompt_options[:select_datastore] = true
|
583
|
+
instance_prompt_options[:name_required] = true
|
584
|
+
# this provisioning helper method handles all (most) of the parsing and prompting
|
585
|
+
instance_config_payload = prompt_new_instance(instance_prompt_options)
|
586
|
+
return instance_config_payload
|
587
|
+
end
|
509
588
|
end
|
@@ -456,32 +456,6 @@ EOT
|
|
456
456
|
opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
|
457
457
|
options[:options]['labels'] = parse_labels(val)
|
458
458
|
end
|
459
|
-
opts.on('--logo FILE', String, "Upload a custom logo icon") do |val|
|
460
|
-
filename = val
|
461
|
-
logo_file = nil
|
462
|
-
if filename == 'null'
|
463
|
-
logo_file = 'null' # clear it
|
464
|
-
else
|
465
|
-
filename = File.expand_path(filename)
|
466
|
-
if !File.exist?(filename)
|
467
|
-
raise_command_error "File not found: #{filename}"
|
468
|
-
end
|
469
|
-
logo_file = File.new(filename, 'rb')
|
470
|
-
end
|
471
|
-
end
|
472
|
-
opts.on('--dark-logo FILE', String, "Upload a custom dark logo icon") do |val|
|
473
|
-
filename = val
|
474
|
-
dark_logo_file = nil
|
475
|
-
if filename == 'null'
|
476
|
-
dark_logo_file = 'null' # clear it
|
477
|
-
else
|
478
|
-
filename = File.expand_path(filename)
|
479
|
-
if !File.exist?(filename)
|
480
|
-
raise_command_error "File not found: #{filename}"
|
481
|
-
end
|
482
|
-
dark_logo_file = File.new(filename, 'rb')
|
483
|
-
end
|
484
|
-
end
|
485
459
|
opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
|
486
460
|
options[:config_file] = val.to_s
|
487
461
|
file_content = nil
|
@@ -41,6 +41,12 @@ class Morpheus::Cli::Clouds
|
|
41
41
|
opts.on( '-t', '--type TYPE', "Cloud Type" ) do |val|
|
42
42
|
options[:zone_type] = val
|
43
43
|
end
|
44
|
+
opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val|
|
45
|
+
add_query_parameter(params, 'labels', parse_labels(val))
|
46
|
+
end
|
47
|
+
opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
|
48
|
+
add_query_parameter(params, 'allLabels', parse_labels(val))
|
49
|
+
end
|
44
50
|
build_standard_list_options(opts, options)
|
45
51
|
opts.footer = "List clouds."
|
46
52
|
end
|
@@ -179,6 +185,7 @@ class Morpheus::Cli::Clouds
|
|
179
185
|
"Type" => lambda {|it| it['zoneType'] ? it['zoneType']['name'] : '' },
|
180
186
|
"Code" => 'code',
|
181
187
|
"Location" => 'location',
|
188
|
+
"Labels" => lambda {|it| format_list(it['labels'], '') rescue '' },
|
182
189
|
"Region Code" => 'regionCode',
|
183
190
|
"Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
|
184
191
|
"Groups" => lambda {|it| it['groups'].collect {|g| g.instance_of?(Hash) ? g['name'] : g.to_s }.join(', ') },
|
@@ -229,6 +236,9 @@ class Morpheus::Cli::Clouds
|
|
229
236
|
opts.on('--credential VALUE', String, "Credential ID or \"local\"" ) do |val|
|
230
237
|
options[:options]['credential'] = val
|
231
238
|
end
|
239
|
+
opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
|
240
|
+
options[:options]['labels'] = parse_labels(val)
|
241
|
+
end
|
232
242
|
|
233
243
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
234
244
|
end
|
@@ -342,6 +352,9 @@ class Morpheus::Cli::Clouds
|
|
342
352
|
# opts.on( '-d', '--description DESCRIPTION', "Description (optional)" ) do |desc|
|
343
353
|
# params[:description] = desc
|
344
354
|
# end
|
355
|
+
opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
|
356
|
+
options[:options]['labels'] = parse_labels(val)
|
357
|
+
end
|
345
358
|
opts.on('--costing-mode VALUE', String, "Costing Mode can be off, costing, or full. Default is off." ) do |val|
|
346
359
|
options[:options]['costingMode'] = val
|
347
360
|
end
|
@@ -400,6 +413,9 @@ class Morpheus::Cli::Clouds
|
|
400
413
|
if params['zone'].is_a?(Hash)
|
401
414
|
cloud_payload.merge!(params.delete('zone'))
|
402
415
|
end
|
416
|
+
if params.key?('labels')
|
417
|
+
params['labels'] = parse_labels(params['labels'])
|
418
|
+
end
|
403
419
|
cloud_payload.merge!(params)
|
404
420
|
payload = {zone: cloud_payload}
|
405
421
|
end
|
@@ -1141,6 +1157,7 @@ EOT
|
|
1141
1157
|
"ID" => 'id',
|
1142
1158
|
"Name" => 'name',
|
1143
1159
|
"Type" => lambda {|it| it['zoneType'] ? it['zoneType']['name'] : '' },
|
1160
|
+
"Labels" => lambda {|it| format_list(it['labels'], '', 3) rescue '' },
|
1144
1161
|
"Location" => 'location',
|
1145
1162
|
"Region Code" => lambda {|it| it['regionCode'] },
|
1146
1163
|
"Groups" => lambda {|it| (it['groups'] || []).collect {|g| g.instance_of?(Hash) ? g['name'] : g.to_s }.join(', ') },
|
@@ -1155,10 +1172,11 @@ EOT
|
|
1155
1172
|
#{'fieldName' => 'zoneType.code', 'fieldLabel' => 'Image Type', 'type' => 'select', 'selectOptions' => cloud_types_for_dropdown, 'required' => true, 'description' => 'Cloud Type.', 'displayOrder' => 0},
|
1156
1173
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
1157
1174
|
{'fieldName' => 'code', 'fieldLabel' => 'Code', 'type' => 'text', 'required' => false, 'displayOrder' => 2},
|
1158
|
-
{'fieldName' => '
|
1159
|
-
{'fieldName' => '
|
1160
|
-
{'fieldName' => '
|
1161
|
-
{'fieldName' => '
|
1175
|
+
{'shorthand' => '-l', 'optionalValue' => true, 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'processValue' => lambda {|val| parse_labels(val) }, 'displayOrder' => 3},
|
1176
|
+
{'fieldName' => 'location', 'fieldLabel' => 'Location', 'type' => 'text', 'required' => false, 'displayOrder' => 4},
|
1177
|
+
{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'},{'name' => 'Public', 'value' => 'public'}], 'required' => false, 'description' => 'Visibility', 'category' => 'permissions', 'defaultValue' => 'private', 'displayOrder' => 5},
|
1178
|
+
{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'required' => false, 'defaultValue' => true, 'displayOrder' => 6},
|
1179
|
+
{'fieldName' => 'autoRecoverPowerState', 'fieldLabel' => 'Automatically Power On VMs', 'type' => 'checkbox', 'required' => false, 'defaultValue' => false, 'displayOrder' => 7}
|
1162
1180
|
]
|
1163
1181
|
|
1164
1182
|
# TODO: Account
|
@@ -33,7 +33,7 @@ class Morpheus::Cli::CurlCommand
|
|
33
33
|
raise ::OptionParser::InvalidOption.new("Failed to parse payload as JSON. Error: #{ex.message}")
|
34
34
|
end
|
35
35
|
end
|
36
|
-
opts.on('--absolute', "Absolute path,
|
36
|
+
opts.on('--absolute', "Absolute path, skip the addition of path prefix '/api/'") do
|
37
37
|
options[:absolute_path] = true
|
38
38
|
end
|
39
39
|
opts.on('--inspect', "Inspect response, prints headers. By default only the body is printed.") do
|
@@ -5,6 +5,7 @@ class Morpheus::Cli::DashboardCommand
|
|
5
5
|
include Morpheus::Cli::ProvisioningHelper
|
6
6
|
set_command_name :dashboard
|
7
7
|
set_command_description "View Morpheus Dashboard"
|
8
|
+
set_command_hidden
|
8
9
|
|
9
10
|
def initialize()
|
10
11
|
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
@@ -16,7 +17,7 @@ class Morpheus::Cli::DashboardCommand
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def usage
|
19
|
-
"Usage: morpheus #{command_name}"
|
20
|
+
"#{yellow}API for this command has been removed starting with appliance version 6.2.6\n#{reset}Usage: morpheus #{command_name}"
|
20
21
|
end
|
21
22
|
|
22
23
|
def handle(args)
|
@@ -31,6 +31,12 @@ class Morpheus::Cli::Groups
|
|
31
31
|
params = {}
|
32
32
|
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
33
33
|
opts.banner = subcommand_usage()
|
34
|
+
opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val|
|
35
|
+
add_query_parameter(params, 'labels', parse_labels(val))
|
36
|
+
end
|
37
|
+
opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
|
38
|
+
add_query_parameter(params, 'allLabels', parse_labels(val))
|
39
|
+
end
|
34
40
|
build_standard_list_options(opts, options)
|
35
41
|
opts.footer = "List groups."
|
36
42
|
end
|
@@ -100,6 +106,14 @@ EOT
|
|
100
106
|
return 0 if render_result
|
101
107
|
|
102
108
|
group = json_response['group']
|
109
|
+
group_stats = group['stats']
|
110
|
+
# serverCounts moved to zone.stats.serverCounts
|
111
|
+
server_counts = nil
|
112
|
+
instance_counts = nil
|
113
|
+
if group_stats
|
114
|
+
instance_counts = group_stats['instanceCounts']
|
115
|
+
server_counts = group_stats['serverCounts']
|
116
|
+
end
|
103
117
|
is_active = @active_group_id && (@active_group_id == group['id'])
|
104
118
|
print_h1 "Group Details"
|
105
119
|
print cyan
|
@@ -108,10 +122,28 @@ EOT
|
|
108
122
|
"Name" => 'name',
|
109
123
|
"Code" => 'code',
|
110
124
|
"Location" => 'location',
|
125
|
+
"Labels" => lambda {|it| format_list(it['labels'], '') rescue '' },
|
111
126
|
"Clouds" => lambda {|it| it['zones'].collect {|z| z['name'] }.join(', ') },
|
112
|
-
"
|
127
|
+
#"Instances" => lambda {|it| it['stats']['instanceCounts']['all'] rescue '' },
|
128
|
+
# "Hosts" => lambda {|it| it['stats']['serverCounts']['host'] rescue it['serverCount'] },
|
129
|
+
# "VMs" => lambda {|it| it['stats']['serverCounts']['vm'] rescue '' },
|
130
|
+
# "Bare Metal" => lambda {|it| it['stats']['serverCounts']['baremetal'] rescue '' },
|
113
131
|
}
|
114
132
|
print_description_list(description_cols, group)
|
133
|
+
|
134
|
+
if server_counts
|
135
|
+
print_h2 "Group Stats"
|
136
|
+
print cyan
|
137
|
+
print "Clouds: #{group['zones'].size}".center(20)
|
138
|
+
print "Instances: #{instance_counts['all']}".center(20) if instance_counts
|
139
|
+
print "Hosts: #{server_counts['host']}".center(20)
|
140
|
+
#print "Container Hosts: #{server_counts['containerHost']}".center(20)
|
141
|
+
#print "Hypervisors: #{server_counts['hypervisor']}".center(20)
|
142
|
+
print "Virtual Machines: #{server_counts['vm']}".center(20)
|
143
|
+
print "Bare Metal: #{server_counts['baremetal']}".center(20)
|
144
|
+
#print "Unmanaged: #{server_counts['unmanaged']}".center(20)
|
145
|
+
print "\n"
|
146
|
+
end
|
115
147
|
# puts "ID: #{group['id']}"
|
116
148
|
# puts "Name: #{group['name']}"
|
117
149
|
# puts "Code: #{group['code']}"
|
@@ -211,10 +243,12 @@ EOT
|
|
211
243
|
params = options[:options] || {}
|
212
244
|
|
213
245
|
if params.empty?
|
214
|
-
|
215
|
-
exit 1
|
246
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
216
247
|
end
|
217
248
|
|
249
|
+
if params.key?('labels')
|
250
|
+
params['labels'] = parse_labels(params['labels'])
|
251
|
+
end
|
218
252
|
group_payload.merge!(params)
|
219
253
|
|
220
254
|
payload = {group: group_payload}
|
@@ -638,18 +672,26 @@ EOT
|
|
638
672
|
{
|
639
673
|
id: active_group ? (((@active_group_id && (@active_group_id == group['id'])) ? "=> " : " ") + group['id'].to_s) : group['id'],
|
640
674
|
name: group['name'],
|
675
|
+
labels: group['labels'],
|
641
676
|
location: group['location'],
|
642
677
|
cloud_count: group['zones'] ? group['zones'].size : 0,
|
643
|
-
|
678
|
+
instance_count: (group['stats']['instanceCounts']['all'] rescue ''),
|
679
|
+
host_count: (group['stats']['serverCounts']['host'] rescue group['serverCount']),
|
680
|
+
vm_count: (group['stats']['serverCounts']['vm'] rescue ''),
|
681
|
+
baremetal_count: (group['stats']['serverCounts']['baremetal'] rescue '')
|
644
682
|
}
|
645
683
|
end
|
646
684
|
columns = [
|
647
685
|
#{:active => {:display_name => ""}},
|
648
686
|
{:id => {:display_name => (active_group ? " ID" : "ID")}},
|
649
|
-
{:name => {:width =>
|
687
|
+
{:name => {:width => 64}},
|
650
688
|
{:location => {:width => 32}},
|
689
|
+
{:labels => {:display_method => lambda {|it| format_list(it[:labels], '', 3) rescue '' }}},
|
651
690
|
{:cloud_count => {:display_name => "CLOUDS"}},
|
652
|
-
{:
|
691
|
+
{:instance_count => {:display_name => "INSTANCES"}},
|
692
|
+
{:host_count => {:display_name => "HOSTS"}},
|
693
|
+
{:vm_count => {:display_name => "VMS"}},
|
694
|
+
{:baremetal_count => {:display_name => "BARE METAL"}},
|
653
695
|
]
|
654
696
|
print as_pretty_table(rows, columns, opts)
|
655
697
|
end
|
@@ -658,7 +700,8 @@ EOT
|
|
658
700
|
tmp_option_types = [
|
659
701
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
660
702
|
{'fieldName' => 'code', 'fieldLabel' => 'Code', 'type' => 'text', 'required' => false, 'displayOrder' => 2},
|
661
|
-
{'fieldName' => '
|
703
|
+
{'shorthand' => '-l', 'optionalValue' => true, 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'processValue' => lambda {|val| parse_labels(val) }, 'displayOrder' => 3},
|
704
|
+
{'fieldName' => 'location', 'fieldLabel' => 'Location', 'type' => 'text', 'required' => false, 'displayOrder' => 4},
|
662
705
|
]
|
663
706
|
|
664
707
|
# Advanced Options
|
@@ -323,7 +323,7 @@ EOT
|
|
323
323
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Form name'},
|
324
324
|
{'fieldName' => 'code', 'fieldLabel' => 'Code', 'type' => 'text', 'required' => true, 'description' => 'Unique form code'},
|
325
325
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text'},
|
326
|
-
{'shorthand' => '-l', 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }},
|
326
|
+
{'shorthand' => '-l', 'optionalValue' => true, 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }},
|
327
327
|
]
|
328
328
|
end
|
329
329
|
|
@@ -431,7 +431,7 @@ class Morpheus::Cli::LibraryOptionListsCommand
|
|
431
431
|
# rest
|
432
432
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
433
433
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2},
|
434
|
-
{'shorthand' => '-l', 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }, 'displayOrder' => 3},
|
434
|
+
{'shorthand' => '-l', 'optionalValue' => true, 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }, 'displayOrder' => 3},
|
435
435
|
{'code' => 'optionTypeList.type', 'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => get_available_option_list_types, 'defaultValue' => 'rest', 'required' => true, 'description' => 'Option List Type. eg. rest, api, ldap, manual', 'displayOrder' => 4},
|
436
436
|
{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'}, {'name' => 'Public', 'value' => 'public'}], 'defaultValue' => 'private', 'displayOrder' => 5},
|
437
437
|
{'dependsOnCode' => 'optionTypeList.type:rest', 'fieldName' => 'sourceUrl', 'fieldLabel' => 'Source Url', 'type' => 'text', 'required' => true, 'description' => "A REST URL can be used to fetch list data and is cached in the appliance database.", 'displayOrder' => 6},
|
@@ -302,7 +302,7 @@ class Morpheus::Cli::LibraryOptionTypesCommand
|
|
302
302
|
[
|
303
303
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
304
304
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2},
|
305
|
-
{'shorthand' => '-l', 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }, 'displayOrder' => 3},
|
305
|
+
{'shorthand' => '-l', 'optionalValue' => true, 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }, 'displayOrder' => 3},
|
306
306
|
{'fieldName' => 'fieldName', 'fieldLabel' => 'Field Name', 'type' => 'text', 'required' => true, 'description' => 'This is the input property that the value gets assigned to.', 'displayOrder' => 4},
|
307
307
|
{'code' => 'optionType.type', 'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => [{'name' => 'Text', 'value' => 'text'}, {'name' => 'Password', 'value' => 'password'}, {'name' => 'Number', 'value' => 'number'}, {'name' => 'Checkbox', 'value' => 'checkbox'}, {'name' => 'Select', 'value' => 'select'}, {'name' => 'Hidden', 'value' => 'hidden'}], 'defaultValue' => 'text', 'required' => true, 'displayOrder' => 5},
|
308
308
|
{'fieldName' => 'optionList', 'fieldLabel' => 'Option List', 'type' => 'select', 'optionSource' => 'optionTypeLists', 'required' => true, 'dependsOnCode' => 'optionType.type:select', 'description' => "The Option List to be the source of options when type is 'select'.", 'displayOrder' => 6},
|
@@ -132,7 +132,7 @@ class Morpheus::Cli::NetworksCommand
|
|
132
132
|
pool: subnet['pool'] ? subnet['pool']['name'] : '',
|
133
133
|
dhcp: subnet['dhcpServer'] ? 'Yes' : 'No',
|
134
134
|
visibility: subnet['visibility'].to_s.capitalize,
|
135
|
-
active: format_boolean(
|
135
|
+
active: format_boolean(subnet['active']),
|
136
136
|
tenants: subnet['tenants'] ? subnet['tenants'].collect {|it| it['name'] }.uniq.join(', ') : ''
|
137
137
|
}
|
138
138
|
rows << subnet_row
|
@@ -57,7 +57,7 @@ class Morpheus::Cli::SecurityPackagesCommand
|
|
57
57
|
api_client.security_package_types.list({max:10000})['securityPackageTypes'].collect { |it| {"name" => it["name"], "value" => it["code"]} }
|
58
58
|
}, 'required' => true, 'defaultValue' => 'SCAP Package'},
|
59
59
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
|
60
|
-
{'shorthand' => '-l', 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }},
|
60
|
+
{'shorthand' => '-l', 'optionalValue' => true, 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }},
|
61
61
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false},
|
62
62
|
{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'required' => false, 'defaultValue' => true},
|
63
63
|
# {'code' => 'securityPackage.sourceType', 'fieldName' => 'sourceType', 'fieldLabel' => 'Source', 'type' => 'select', 'selectOptions' => [{'name'=>'url','value'=>'url'}], 'defaultValue' => 'url', 'required' => true},
|
@@ -385,7 +385,7 @@ EOT
|
|
385
385
|
|
386
386
|
if hubmode == 'skip'
|
387
387
|
if ::Morpheus::Cli::OptionTypes::confirm("Would you like to install your License Key now?", options.merge({:default => true}))
|
388
|
-
cmd_res = Morpheus::Cli::License.new.
|
388
|
+
cmd_res = Morpheus::Cli::License.new.install([] + (options[:remote] ? ["-r",options[:remote]] : []))
|
389
389
|
# license_is_valid = cmd_res != false
|
390
390
|
end
|
391
391
|
end
|
@@ -1373,11 +1373,11 @@ class Morpheus::Cli::Tasks
|
|
1373
1373
|
# this makes us all sad
|
1374
1374
|
option_types.each do |option_type|
|
1375
1375
|
if option_type['type'] == 'typeahead'
|
1376
|
-
if ['operationalWorkflowName','containerScript','containerTemplate'].include?(option_type['code'])
|
1376
|
+
if ['operationalWorkflowName','ifOperationalWorkflowName','elseOperationalWorkflowName','containerScript','containerTemplate'].include?(option_type['code'])
|
1377
1377
|
option_type.deep_merge!({'config' => {'valueField' => 'name'}})
|
1378
1378
|
end
|
1379
1379
|
elsif option_type['type'] == 'hidden'
|
1380
|
-
if ['operationalWorkflowId','containerScriptId','containerTemplateId'].include?(option_type['code'])
|
1380
|
+
if ['operationalWorkflowId','ifOperationalWorkflowId','elseOperationalWorkflowId','containerScriptId','containerTemplateId'].include?(option_type['code'])
|
1381
1381
|
option_type['processValue'] = lambda {|val|
|
1382
1382
|
if val.to_s.empty?
|
1383
1383
|
selected_option = Morpheus::Cli::OptionTypes.get_last_select()
|
@@ -104,7 +104,16 @@ EOT
|
|
104
104
|
"ACCESS TOKEN" => lambda {|it| it['maskedAccessToken'] },
|
105
105
|
"REFRESH TOKEN" => lambda {|it| it['maskedRefreshToken'] },
|
106
106
|
"ACCESS EXPIRATION" => lambda {|it| format_local_dt(it['expiration']) },
|
107
|
-
"ACCESS TTL" => lambda {|it|
|
107
|
+
"ACCESS TTL" => lambda {|it|
|
108
|
+
if it['expiration']
|
109
|
+
expires_on = parse_time(it['expiration'])
|
110
|
+
if expires_on && expires_on < Time.now
|
111
|
+
"Expired"
|
112
|
+
else
|
113
|
+
it['expiration'] ? (format_duration(it['expiration']) rescue '') : ''
|
114
|
+
end
|
115
|
+
end
|
116
|
+
}
|
108
117
|
}
|
109
118
|
print cyan
|
110
119
|
puts as_pretty_table(access_tokens, cols)
|
@@ -119,10 +119,10 @@ module Morpheus::Cli::BackupsHelper
|
|
119
119
|
"Backup" => lambda {|it| it['backup']['name'] rescue '' },
|
120
120
|
"Status" => lambda {|it| format_backup_result_status(it) },
|
121
121
|
#"Duration" => lambda {|it| format_duration(it['startDate'], it['endDate']) },
|
122
|
-
"Duration" => lambda {|it| format_duration_milliseconds(it['durationMillis']) },
|
122
|
+
"Duration" => lambda {|it| format_duration_milliseconds(it['durationMillis']) if it['durationMillis'].to_i > 0 },
|
123
123
|
"Start Date" => lambda {|it| format_local_dt(it['startDate']) },
|
124
124
|
"End Date" => lambda {|it| format_local_dt(it['endDate']) },
|
125
|
-
"Size" => lambda {|it| format_bytes(it['sizeInMb'], 'MB') },
|
125
|
+
"Size" => lambda {|it| it['sizeInMb'].to_i != 0 ? format_bytes(it['sizeInMb'], 'MB') : '' },
|
126
126
|
}
|
127
127
|
end
|
128
128
|
|
@@ -155,7 +155,7 @@ module Morpheus::Cli::BackupsHelper
|
|
155
155
|
"Target" => lambda {|it| it['instance']['name'] rescue '' },
|
156
156
|
"Status" => lambda {|it| format_backup_result_status(it) },
|
157
157
|
#"Duration" => lambda {|it| format_duration(it['startDate'], it['endDate']) },
|
158
|
-
"Duration" => lambda {|it| format_duration_milliseconds(it['durationMillis']) },
|
158
|
+
"Duration" => lambda {|it| format_duration_milliseconds(it['durationMillis']) if it['durationMillis'].to_i > 0 },
|
159
159
|
"Start Date" => lambda {|it| format_local_dt(it['startDate']) },
|
160
160
|
"End Date" => lambda {|it| format_local_dt(it['endDate']) },
|
161
161
|
}
|
@@ -168,4 +168,5 @@ module Morpheus::Cli::BackupsHelper
|
|
168
168
|
def format_backup_restore_status(backup_restore, return_color=cyan)
|
169
169
|
format_backup_result_status(backup_restore, return_color)
|
170
170
|
end
|
171
|
+
|
171
172
|
end
|
@@ -1113,8 +1113,15 @@ module Morpheus
|
|
1113
1113
|
value_found = false
|
1114
1114
|
value = nil
|
1115
1115
|
while !value_found do
|
1116
|
-
print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? (' (' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
|
1117
|
-
input = $stdin.gets.chomp!
|
1116
|
+
# print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? (' (' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
|
1117
|
+
# input = $stdin.gets.chomp!
|
1118
|
+
Readline.completion_append_character = ""
|
1119
|
+
Readline.basic_word_break_characters = ''
|
1120
|
+
Readline.completion_proc = nil
|
1121
|
+
prompt_label = "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? (' (' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
|
1122
|
+
input = Readline.readline(prompt_label, false).to_s
|
1123
|
+
input = input.chomp #.strip
|
1124
|
+
|
1118
1125
|
value = input.empty? ? option_type['defaultValue'] : input
|
1119
1126
|
if input == '?'
|
1120
1127
|
help_prompt(option_type)
|
data/lib/morpheus/cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: morpheus-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.3.
|
4
|
+
version: 6.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Estes
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2024-02-15 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -204,6 +204,7 @@ files:
|
|
204
204
|
- lib/morpheus/api/backup_service_types_interface.rb
|
205
205
|
- lib/morpheus/api/backup_services_interface.rb
|
206
206
|
- lib/morpheus/api/backup_settings_interface.rb
|
207
|
+
- lib/morpheus/api/backup_types_interface.rb
|
207
208
|
- lib/morpheus/api/backups_interface.rb
|
208
209
|
- lib/morpheus/api/billing_interface.rb
|
209
210
|
- lib/morpheus/api/blueprints_interface.rb
|
@@ -381,6 +382,7 @@ files:
|
|
381
382
|
- lib/morpheus/cli/commands/backup_results_command.rb
|
382
383
|
- lib/morpheus/cli/commands/backup_services_command.rb
|
383
384
|
- lib/morpheus/cli/commands/backup_settings_command.rb
|
385
|
+
- lib/morpheus/cli/commands/backup_types_command.rb
|
384
386
|
- lib/morpheus/cli/commands/backups_command.rb
|
385
387
|
- lib/morpheus/cli/commands/benchmark_command.rb
|
386
388
|
- lib/morpheus/cli/commands/blueprints_command.rb
|