morpheus-cli 6.3.3 → 6.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +3 -0
- 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/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']
|
@@ -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
|
@@ -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: 2024-
|
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
|