morpheus-cli 7.0.7 → 8.0.1
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 +11 -0
- data/lib/morpheus/api/appliance_settings_interface.rb +7 -0
- data/lib/morpheus/api/clusters_interface.rb +25 -0
- data/lib/morpheus/api/datastores_interface.rb +6 -0
- data/lib/morpheus/api/library_operating_systems_interface.rb +63 -0
- data/lib/morpheus/api/processes_interface.rb +17 -5
- data/lib/morpheus/api/virtual_images_interface.rb +6 -0
- data/lib/morpheus/cli/commands/appliance_settings_command.rb +21 -2
- data/lib/morpheus/cli/commands/apps.rb +1 -1
- data/lib/morpheus/cli/commands/backup_jobs_command.rb +50 -17
- data/lib/morpheus/cli/commands/backups_command.rb +36 -9
- data/lib/morpheus/cli/commands/clouds.rb +1 -1
- data/lib/morpheus/cli/commands/clusters.rb +380 -6
- data/lib/morpheus/cli/commands/hosts.rb +3 -0
- data/lib/morpheus/cli/commands/instances.rb +33 -4
- data/lib/morpheus/cli/commands/library_container_types_command.rb +6 -0
- data/lib/morpheus/cli/commands/library_operating_systems_command.rb +671 -0
- data/lib/morpheus/cli/commands/license.rb +11 -1
- data/lib/morpheus/cli/commands/processes_command.rb +71 -1
- data/lib/morpheus/cli/commands/setup.rb +32 -18
- data/lib/morpheus/cli/commands/virtual_images.rb +66 -8
- data/lib/morpheus/cli/mixins/print_helper.rb +4 -2
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +35 -8
- data/lib/morpheus/cli/option_types.rb +3 -0
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/formatters.rb +12 -0
- metadata +5 -3
@@ -294,6 +294,13 @@ class Morpheus::Cli::License
|
|
294
294
|
elsif license['zoneTypesExcluded'] && license['zoneTypesExcluded'].size > 0
|
295
295
|
description_cols["Excluded Clouds"] = lambda {|it| it['zoneTypesExcluded'].join(', ') }
|
296
296
|
end
|
297
|
+
|
298
|
+
if license['taskTypes'] && license['taskTypes'].size > 0
|
299
|
+
description_cols["Included Tasks"] = lambda {|it| it['taskTypes'].join(', ') }
|
300
|
+
elsif license['taskTypesExcluded'] && license['taskTypesExcluded'].size > 0
|
301
|
+
description_cols["Excluded Tasks"] = lambda {|it| it['taskTypesExcluded'].join(', ') }
|
302
|
+
end
|
303
|
+
|
297
304
|
print_description_list(description_cols, license)
|
298
305
|
end
|
299
306
|
|
@@ -306,6 +313,7 @@ class Morpheus::Cli::License
|
|
306
313
|
used_discovered_servers = current_usage['discoveredServers']
|
307
314
|
used_hosts = current_usage['hosts']
|
308
315
|
used_mvm = current_usage['mvm']
|
316
|
+
used_mvm_sockets = current_usage['mvmSockets']
|
309
317
|
used_iac = current_usage['iac']
|
310
318
|
used_xaas = current_usage['xaas']
|
311
319
|
used_executions = current_usage['executions']
|
@@ -317,6 +325,7 @@ class Morpheus::Cli::License
|
|
317
325
|
max_discovered_servers = license['maxDiscoveredServers']
|
318
326
|
max_hosts = license['maxHosts']
|
319
327
|
max_mvm = license['maxMvm']
|
328
|
+
max_mvm_sockets = license['maxMvmSockets']
|
320
329
|
max_iac = license['maxIac']
|
321
330
|
max_xaas = license['maxXaas']
|
322
331
|
max_executions = license['maxExecutions']
|
@@ -328,7 +337,8 @@ class Morpheus::Cli::License
|
|
328
337
|
out << cyan + "Managed Servers".rjust(label_width, ' ') + ": " + generate_usage_bar(used_managed_servers, max_managed_servers, chart_opts) + cyan + used_managed_servers.to_s.rjust(8, ' ') + " / " + (max_managed_servers ? max_managed_servers.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
|
329
338
|
out << cyan + "Discovered Servers".rjust(label_width, ' ') + ": " + generate_usage_bar(used_discovered_servers, max_discovered_servers, chart_opts) + cyan + used_discovered_servers.to_s.rjust(8, ' ') + " / " + (max_discovered_servers ? max_discovered_servers.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
|
330
339
|
out << cyan + "Hosts".rjust(label_width, ' ') + ": " + generate_usage_bar(used_hosts, max_hosts, chart_opts) + cyan + used_hosts.to_s.rjust(8, ' ') + " / " + (max_hosts ? max_hosts.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
|
331
|
-
out << cyan + "
|
340
|
+
out << cyan + "HPE VM Hosts".rjust(label_width, ' ') + ": " + generate_usage_bar(used_mvm, max_mvm, chart_opts) + cyan + used_mvm.to_s.rjust(8, ' ') + " / " + (max_mvm ? max_mvm.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
|
341
|
+
out << cyan + "HPE VM Sockets".rjust(label_width, ' ') + ": " + generate_usage_bar(used_mvm_sockets, max_mvm_sockets, chart_opts) + cyan + used_mvm_sockets.to_s.rjust(8, ' ') + " / " + (max_mvm_sockets ? max_mvm_sockets.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
|
332
342
|
out << cyan + "Iac Deployments".rjust(label_width, ' ') + ": " + generate_usage_bar(used_iac, max_iac, chart_opts) + cyan + used_iac.to_s.rjust(8, ' ') + " / " + (max_iac ? max_iac.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
|
333
343
|
out << cyan + "Xaas Instances".rjust(label_width, ' ') + ": " + generate_usage_bar(used_xaas, max_xaas, chart_opts) + cyan + used_xaas.to_s.rjust(8, ' ') + " / " + (max_xaas ? max_xaas.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
|
334
344
|
out << cyan + "Executions".rjust(label_width, ' ') + ": " + generate_usage_bar(used_executions, max_executions, chart_opts) + cyan + used_executions.to_s.rjust(8, ' ') + " / " + (max_executions ? max_executions.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
|
@@ -9,7 +9,7 @@ class Morpheus::Cli::Processes
|
|
9
9
|
|
10
10
|
set_command_name :'process'
|
11
11
|
|
12
|
-
register_subcommands :list, :get, {:'get-event' => :event_details}
|
12
|
+
register_subcommands :list, :get, {:'get-event' => :event_details}, :retry, :cancel
|
13
13
|
|
14
14
|
# alias_subcommand :details, :get
|
15
15
|
# set_default_subcommand :list
|
@@ -346,6 +346,76 @@ class Morpheus::Cli::Processes
|
|
346
346
|
end
|
347
347
|
end
|
348
348
|
|
349
|
+
def retry(args)
|
350
|
+
options = {}
|
351
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
352
|
+
opts.banner = subcommand_usage("[id]")
|
353
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
354
|
+
opts.footer = <<-EOT
|
355
|
+
Retry a process.
|
356
|
+
[id] is required. This is the id of a process.
|
357
|
+
Only a process that is failed or cancelled and is of a retryable type can be retried.
|
358
|
+
EOT
|
359
|
+
end
|
360
|
+
optparse.parse!(args)
|
361
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
362
|
+
connect(options)
|
363
|
+
# process = find_process_by_id(args[0])
|
364
|
+
# return 1 if process.nil?
|
365
|
+
process_id = args[0]
|
366
|
+
payload = parse_payload(options)
|
367
|
+
if payload.nil?
|
368
|
+
payload = parse_passed_options(options)
|
369
|
+
# prompt
|
370
|
+
end
|
371
|
+
confirm!("Are you sure you would like to retry process #{process_id}?", options)
|
372
|
+
@processes_interface.setopts(options)
|
373
|
+
if options[:dry_run]
|
374
|
+
print_dry_run @processes_interface.dry.retry(process_id, payload)
|
375
|
+
return
|
376
|
+
end
|
377
|
+
json_response = @processes_interface.retry(process_id, payload)
|
378
|
+
render_response(json_response, options) do
|
379
|
+
print_green_success "Retrying process #{process_id}"
|
380
|
+
end
|
381
|
+
return 0, nil
|
382
|
+
end
|
383
|
+
|
384
|
+
def cancel(args)
|
385
|
+
options = {}
|
386
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
387
|
+
opts.banner = subcommand_usage("[id]")
|
388
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
389
|
+
opts.footer = <<-EOT
|
390
|
+
Cancel a process.
|
391
|
+
[id] is required. This is the id of a process.
|
392
|
+
Only a process that is currently running and is of a cancellable type can be canceled.
|
393
|
+
EOT
|
394
|
+
end
|
395
|
+
optparse.parse!(args)
|
396
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
397
|
+
connect(options)
|
398
|
+
# process = find_process_by_id(args[0])
|
399
|
+
# return 1 if process.nil?
|
400
|
+
process_id = args[0]
|
401
|
+
payload = parse_payload(options)
|
402
|
+
if payload.nil?
|
403
|
+
payload = parse_passed_options(options)
|
404
|
+
# prompt
|
405
|
+
end
|
406
|
+
confirm!("Are you sure you would like to cancel process #{process_id}?", options)
|
407
|
+
@processes_interface.setopts(options)
|
408
|
+
if options[:dry_run]
|
409
|
+
print_dry_run @processes_interface.dry.cancel(process_id, payload)
|
410
|
+
return
|
411
|
+
end
|
412
|
+
json_response = @processes_interface.cancel(process_id, payload)
|
413
|
+
render_response(json_response, options) do
|
414
|
+
print_green_success "Cancelling process #{process_id}"
|
415
|
+
end
|
416
|
+
return 0, nil
|
417
|
+
end
|
418
|
+
|
349
419
|
def event_details(args)
|
350
420
|
options = {}
|
351
421
|
params = {}
|
@@ -35,6 +35,9 @@ class Morpheus::Cli::Setup
|
|
35
35
|
opts.on('--hubmode MODE','--hubmode MODE', "Choose an option for hub registration possible values are login, register, skip.") do |val|
|
36
36
|
options[:hubmode] = val.to_s.downcase
|
37
37
|
end
|
38
|
+
opts.on('--license KEY', String, "License key to install") do |val|
|
39
|
+
options[:license] = val
|
40
|
+
end
|
38
41
|
opts.on('--force','--force', "Force setup, make api request even if setup is unavailable.") do
|
39
42
|
options[:force] = true
|
40
43
|
end
|
@@ -127,10 +130,10 @@ EOT
|
|
127
130
|
puts "It looks like you are the first one here, so let's begin."
|
128
131
|
print reset, "\n"
|
129
132
|
# print "\n"
|
130
|
-
unless Morpheus::Cli::OptionTypes.confirm("Would you like to setup and initialize the remote appliance now?", options)
|
131
|
-
|
132
|
-
end
|
133
|
-
print "\n"
|
133
|
+
# unless Morpheus::Cli::OptionTypes.confirm("Would you like to setup and initialize the remote appliance now?", options)
|
134
|
+
# return 9, "aborted command"
|
135
|
+
# end
|
136
|
+
# print "\n"
|
134
137
|
hubmode = nil
|
135
138
|
hub_init_payload = nil # gets included as payload for hub scoped like hub.email
|
136
139
|
if hub_settings['enabled']
|
@@ -354,6 +357,15 @@ EOT
|
|
354
357
|
payload.delete('hub')
|
355
358
|
end
|
356
359
|
|
360
|
+
# License Key prompt
|
361
|
+
print_h2 "License", options
|
362
|
+
if options[:license]
|
363
|
+
payload['licenseKey'] = options[:license].strip
|
364
|
+
else
|
365
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'licenseKey', 'fieldLabel' => 'License Key', 'type' => 'text', 'description' => "Enter a License Key to install now or leave blank to use a community license or install one manually later."}], options[:options])
|
366
|
+
key = v_prompt['licenseKey']
|
367
|
+
payload['licenseKey'] = key.strip if !key.to_s.strip.empty?
|
368
|
+
end
|
357
369
|
end
|
358
370
|
|
359
371
|
# ok, make the api request
|
@@ -383,24 +395,26 @@ EOT
|
|
383
395
|
print reset
|
384
396
|
#print "\n"
|
385
397
|
|
386
|
-
|
387
|
-
if
|
388
|
-
|
389
|
-
|
398
|
+
unless options[:no_prompt]
|
399
|
+
if hubmode == 'skip' && payload['licenseKey'].to_s.empty?
|
400
|
+
if ::Morpheus::Cli::OptionTypes::confirm("Would you like to install your License Key now?", options.merge({:default => true}))
|
401
|
+
cmd_res = Morpheus::Cli::License.new.install([] + (options[:remote] ? ["-r",options[:remote]] : []))
|
402
|
+
# license_is_valid = cmd_res != false
|
403
|
+
end
|
390
404
|
end
|
391
|
-
end
|
392
405
|
|
393
|
-
|
394
|
-
|
406
|
+
if ::Morpheus::Cli::OptionTypes::confirm("Would you like to create the first group now?", options.merge({:default => true}))
|
407
|
+
cmd_res = Morpheus::Cli::Groups.new.add(['--use'] + (options[:remote] ? ["-r",options[:remote]] : []))
|
395
408
|
|
396
|
-
|
409
|
+
#print "\n"
|
397
410
|
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
411
|
+
# if cmd_res !=
|
412
|
+
if ::Morpheus::Cli::OptionTypes::confirm("Would you like to create the first cloud now?", options.merge({:default => true}))
|
413
|
+
cmd_res = Morpheus::Cli::Clouds.new.add([] + (options[:remote] ? ["-r",options[:remote]] : []))
|
414
|
+
#print "\n"
|
415
|
+
end
|
416
|
+
# end
|
417
|
+
end
|
404
418
|
end
|
405
419
|
print "\n",reset
|
406
420
|
return exit_code, err
|
@@ -6,7 +6,7 @@ class Morpheus::Cli::VirtualImages
|
|
6
6
|
include Morpheus::Cli::CliCommand
|
7
7
|
include Morpheus::Cli::ProvisioningHelper
|
8
8
|
|
9
|
-
register_subcommands :list, :get, :add, :add_file, :remove_file, :update, :remove, :types => :virtual_image_types
|
9
|
+
register_subcommands :list, :get, :add, :add_file, :remove_file, :update, :remove, :convert, :types => :virtual_image_types
|
10
10
|
register_subcommands :list_locations, :get_location, :remove_location
|
11
11
|
|
12
12
|
# def initialize()
|
@@ -302,7 +302,7 @@ EOT
|
|
302
302
|
options = {}
|
303
303
|
tenants_list = nil
|
304
304
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
305
|
-
opts.banner = subcommand_usage("[
|
305
|
+
opts.banner = subcommand_usage("[image] [options]")
|
306
306
|
opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
|
307
307
|
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
308
308
|
tenants_list = []
|
@@ -324,7 +324,7 @@ EOT
|
|
324
324
|
end
|
325
325
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
326
326
|
opts.footer = "Update a virtual image." + "\n" +
|
327
|
-
"[
|
327
|
+
"[image] is required. This is the name or id of a virtual image."
|
328
328
|
end
|
329
329
|
optparse.parse!(args)
|
330
330
|
verify_args!(args:args, optparse:optparse, count:1)
|
@@ -377,6 +377,56 @@ EOT
|
|
377
377
|
|
378
378
|
end
|
379
379
|
|
380
|
+
def convert(args)
|
381
|
+
image_name = args[0]
|
382
|
+
options = {}
|
383
|
+
# storageProviderId, format, name
|
384
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
385
|
+
opts.banner = subcommand_usage("[image] [options]")
|
386
|
+
opts.on('-n', '--name NAME', String, "Name (optional) of the new converted image. Default is name of the original image.") do |val|
|
387
|
+
options[:options]['name'] = val
|
388
|
+
end
|
389
|
+
opts.on('-f', '--format FORMAT', String, "Format (optional). Default is 'qcow2'") do |val|
|
390
|
+
options[:options]['format'] = val
|
391
|
+
end
|
392
|
+
opts.on('--storageProvider VALUE', String, "Storage Provider ID (optional). Default is storage provider of the original image.") do |val|
|
393
|
+
options[:options]['storageProvider'] = val.to_s
|
394
|
+
end
|
395
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
396
|
+
opts.footer = "Convert a virtual image to a new format." + "\n" +
|
397
|
+
"[image] is required. This is the name or id of a virtual image."
|
398
|
+
end
|
399
|
+
optparse.parse!(args)
|
400
|
+
verify_args!(args:args, optparse:optparse, min:1, max:4)
|
401
|
+
|
402
|
+
connect(options)
|
403
|
+
|
404
|
+
virtual_image = find_virtual_image_by_name_or_id(image_name)
|
405
|
+
return 1, "Virtual image not found for #{image_name}" if virtual_image.nil?
|
406
|
+
|
407
|
+
passed_options = parse_passed_options(options)
|
408
|
+
payload = nil
|
409
|
+
if options[:payload]
|
410
|
+
payload = options[:payload]
|
411
|
+
payload.deep_merge!({virtual_image_object_key => passed_options}) unless passed_options.empty?
|
412
|
+
else
|
413
|
+
virtual_image_payload = passed_options
|
414
|
+
virtual_image_payload['storageProvider'] = {'id' => virtual_image_payload['storageProvider']} unless virtual_image_payload['storageProvider'].nil?
|
415
|
+
payload = virtual_image_payload
|
416
|
+
end
|
417
|
+
@virtual_images_interface.setopts(options)
|
418
|
+
if options[:dry_run]
|
419
|
+
print_dry_run @virtual_images_interface.dry.convert(virtual_image['id'], payload)
|
420
|
+
return
|
421
|
+
end
|
422
|
+
json_response = @virtual_images_interface.convert(virtual_image['id'], payload)
|
423
|
+
render_response(json_response, options, 'virtualImage') do
|
424
|
+
print_green_success "Updated virtual image #{virtual_image['name']}"
|
425
|
+
_get(virtual_image["id"], {}, options)
|
426
|
+
end
|
427
|
+
return 0, nil
|
428
|
+
end
|
429
|
+
|
380
430
|
def virtual_image_types(args)
|
381
431
|
options = {}
|
382
432
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
@@ -531,6 +581,7 @@ EOT
|
|
531
581
|
v_prompt.deep_compact!
|
532
582
|
virtual_image_payload.deep_merge!(v_prompt)
|
533
583
|
virtual_image_files = virtual_image_payload.delete('virtualImageFiles')
|
584
|
+
upload_type = virtual_image_payload.delete('uploadType') # not used serverside
|
534
585
|
virtual_image_payload['imageType'] = image_type['code']
|
535
586
|
storage_provider_id = virtual_image_payload.delete('storageProviderId')
|
536
587
|
if !storage_provider_id.to_s.empty?
|
@@ -551,6 +602,11 @@ EOT
|
|
551
602
|
if virtual_image_payload && virtual_image_payload['imageType'] == 'vmware'
|
552
603
|
virtual_image_payload['imageType'] == 'vmdk'
|
553
604
|
end
|
605
|
+
# no need to make second request anymore, just include virtualImage.url
|
606
|
+
if file_url
|
607
|
+
virtual_image_payload['url'] = file_url
|
608
|
+
file_url = nil
|
609
|
+
end
|
554
610
|
#payload = {'virtualImage' => virtual_image_payload}
|
555
611
|
payload.deep_merge!({'virtualImage' => virtual_image_payload})
|
556
612
|
end
|
@@ -615,7 +671,7 @@ EOT
|
|
615
671
|
do_gzip = false
|
616
672
|
options = {}
|
617
673
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
618
|
-
opts.banner = subcommand_usage("[
|
674
|
+
opts.banner = subcommand_usage("[image] [filepath]")
|
619
675
|
opts.on('--filename FILENAME', String, "Filename for uploaded file. Derived from [filepath] by default." ) do |val|
|
620
676
|
file_name = val
|
621
677
|
end
|
@@ -627,7 +683,7 @@ EOT
|
|
627
683
|
end
|
628
684
|
build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
|
629
685
|
opts.footer = "Upload a virtual image file." + "\n" +
|
630
|
-
"[
|
686
|
+
"[image] is required. This is the name or id of a virtual image." + "\n" +
|
631
687
|
"[filepath] or --url is required. This is location of the virtual image file."
|
632
688
|
end
|
633
689
|
optparse.parse!(args)
|
@@ -694,7 +750,7 @@ EOT
|
|
694
750
|
def remove_file(args)
|
695
751
|
options = {}
|
696
752
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
697
|
-
opts.banner = subcommand_usage("[
|
753
|
+
opts.banner = subcommand_usage("[image] [filename]")
|
698
754
|
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
699
755
|
end
|
700
756
|
optparse.parse!(args)
|
@@ -967,7 +1023,7 @@ EOT
|
|
967
1023
|
{'fieldName' => 'installAgent', 'fieldLabel' => 'Install Agent?', 'type' => 'checkbox', 'defaultValue' => 'off', 'required' => false, 'description' => 'Install Agent?', 'displayOrder' => 6},
|
968
1024
|
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text', 'required' => false, 'description' => 'Enter an SSH Username', 'displayOrder' => 7},
|
969
1025
|
{'fieldName' => 'sshPassword', 'fieldLabel' => 'SSH Password', 'type' => 'password', 'required' => false, 'description' => 'Enter an SSH Password', 'displayOrder' => 8},
|
970
|
-
{'fieldName' => 'storageProviderId', 'type' => 'select', 'fieldLabel' => '
|
1026
|
+
{'fieldName' => 'storageProviderId', 'type' => 'select', 'fieldLabel' => 'Bucket', 'optionSource' => 'storageProviders', 'required' => false, 'description' => 'Select Storage Provider.', 'displayOrder' => 9},
|
971
1027
|
{'fieldName' => 'userData', 'fieldLabel' => 'Cloud-Init User Data', 'type' => 'textarea', 'required' => false, 'displayOrder' => 10},
|
972
1028
|
{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'},{'name' => 'Public', 'value' => 'public'}], 'required' => false, 'description' => 'Visibility', 'category' => 'permissions', 'defaultValue' => 'private', 'displayOrder' => 40},
|
973
1029
|
{'fieldName' => 'isAutoJoinDomain', 'fieldLabel' => 'Auto Join Domain?', 'type' => 'checkbox', 'defaultValue' => 'off', 'required' => false, 'description' => 'Auto Join Domain?', 'category' => 'advanced', 'displayOrder' => 40},
|
@@ -999,7 +1055,9 @@ EOT
|
|
999
1055
|
tmp_option_types.reject! {|opt| ['storageProviderId', 'userData', 'sshUsername', 'sshPassword'].include?(opt['fieldName'])}
|
1000
1056
|
else
|
1001
1057
|
if include_file_selection
|
1002
|
-
tmp_option_types << {'
|
1058
|
+
tmp_option_types << {'code' => 'virtualImage.uploadType', 'fieldName' => 'uploadType', 'fieldLabel' => 'Create Image ID', 'type' => 'select', 'selectOptions' => [{'name' => 'File', 'value' => 'file'},{'name' => 'URL/Path', 'value' => 'url'},{'name' => 'None', 'value' => 'none'}], 'defaultValue' => 'file', 'required' => false, 'description' => 'Choose upload type: file, url or none', 'displayOrder' => 11}
|
1059
|
+
tmp_option_types << {'dependsOnCode' => 'virtualImage.uploadType:file', 'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageFile', 'fieldLabel' => 'Image File', 'type' => 'file', 'required' => false, 'description' => 'Choose an image file to upload', 'displayOrder' => 12}
|
1060
|
+
tmp_option_types << {'dependsOnCode' => 'virtualImage.uploadType:url', 'fieldName' => 'url', 'fieldLabel' => 'URL/Path', 'type' => 'text', 'required' => false, 'description' => 'Enter URL/Path to virtual image file(s)', 'displayOrder' => 13}
|
1003
1061
|
end
|
1004
1062
|
end
|
1005
1063
|
end
|
@@ -509,13 +509,15 @@ module Morpheus::Cli::PrintHelper
|
|
509
509
|
bars = []
|
510
510
|
percent = 0
|
511
511
|
percent_sigdig = opts[:percent_sigdig] || 2
|
512
|
-
if max_value.
|
512
|
+
if max_value.nil?
|
513
513
|
percent = 0
|
514
|
+
elsif max_value == 0
|
515
|
+
percent = used_value.to_f == 0 ? 0 : 100
|
514
516
|
else
|
515
517
|
percent = ((used_value.to_f / max_value.to_f) * 100)
|
516
518
|
end
|
517
519
|
unlimited_label = opts[:unlimited_label] || "n/a"
|
518
|
-
percent_label = (
|
520
|
+
percent_label = (max_value.nil? ? unlimited_label : "#{percent.round(percent_sigdig)}%").rjust(6, ' ')
|
519
521
|
bar_display = ""
|
520
522
|
if percent > 100
|
521
523
|
max_bars.times { bars << "|" }
|
@@ -508,16 +508,17 @@ module Morpheus::Cli::ProvisioningHelper
|
|
508
508
|
|
509
509
|
while instance_name.nil? do
|
510
510
|
name_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Instance Name', 'type' => 'text', 'required' => options[:name_required], 'defaultValue' => options[:default_name]}], options[:options])
|
511
|
-
|
512
|
-
if
|
511
|
+
name = name_prompt['name']
|
512
|
+
if name.nil? && !options[:name_required]
|
513
513
|
break
|
514
514
|
else
|
515
|
-
if instances_interface.list({name:
|
516
|
-
instance_name =
|
515
|
+
if instances_interface.list({name: name})['instances'].empty?
|
516
|
+
instance_name = name
|
517
517
|
else
|
518
|
-
print_red_alert "Name must be unique"
|
518
|
+
print_red_alert "Name must be unique, #{name} already exists"
|
519
|
+
options[:options].delete('name')
|
519
520
|
exit 1 if no_prompt
|
520
|
-
if options[:default_name] ==
|
521
|
+
if options[:default_name] == name
|
521
522
|
options[:default_name] += '-2'
|
522
523
|
end
|
523
524
|
end
|
@@ -2150,25 +2151,51 @@ module Morpheus::Cli::ProvisioningHelper
|
|
2150
2151
|
end
|
2151
2152
|
|
2152
2153
|
# Tenants
|
2154
|
+
default_stores = []
|
2155
|
+
default_targets = []
|
2153
2156
|
unless excludes.include?('tenants')
|
2154
2157
|
if !options[:tenants].nil?
|
2155
2158
|
accounts = options[:tenants].collect {|id| id.to_i}
|
2156
2159
|
elsif !options[:no_prompt]
|
2157
2160
|
account_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'account', 'type' => 'select', 'fieldLabel' => 'Add Tenant', 'selectOptions' => available_accounts, 'required' => false, 'description' => 'Add Tenant Permissions.'}], options[:options], @api_client, {})['account']
|
2158
2161
|
|
2159
|
-
|
2162
|
+
unless account_id.nil?
|
2160
2163
|
accounts << account_id
|
2161
2164
|
available_accounts = available_accounts.reject {|it| it['value'] == account_id}
|
2162
2165
|
|
2166
|
+
# Prompt default store / target
|
2167
|
+
if options[:for_datastore]
|
2168
|
+
if Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultTarget', 'type' => 'checkbox', 'fieldLabel' => 'Default', 'required' => false, 'description' => 'Designate as Default Store.', 'defaultValue' => false}], options[:options].merge({:checkbox_as_boolean => true}), @api_client, {})['defaultTarget']
|
2169
|
+
default_targets << account_id
|
2170
|
+
end
|
2171
|
+
if Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultStore', 'type' => 'checkbox', 'fieldLabel' => 'Image Target', 'required' => false, 'description' => 'Designate as Image Target.', 'defaultValue' => false}], options[:options].merge({:checkbox_as_boolean => true}), @api_client, {})['defaultStore']
|
2172
|
+
default_stores << account_id
|
2173
|
+
end
|
2174
|
+
end
|
2175
|
+
|
2163
2176
|
while !available_accounts.empty? && (account_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'account', 'type' => 'select', 'fieldLabel' => 'Add Another Tenant', 'selectOptions' => available_accounts, 'required' => false, 'description' => 'Add Tenant Permissions.'}], options[:options], @api_client, {})['account'])
|
2164
2177
|
if !account_id.nil?
|
2165
2178
|
accounts << account_id
|
2166
2179
|
available_accounts = available_accounts.reject {|it| it['value'] == account_id}
|
2180
|
+
|
2181
|
+
# Prompt default store / target
|
2182
|
+
if options[:for_datastore]
|
2183
|
+
if Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultTarget', 'type' => 'checkbox', 'fieldLabel' => 'Default', 'required' => false, 'description' => 'Designate as Default Store.', 'defaultValue' => false}], options[:options].merge({:checkbox_as_boolean => true}), @api_client, {})['defaultTarget']
|
2184
|
+
default_targets << account_id
|
2185
|
+
end
|
2186
|
+
if Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultStore', 'type' => 'checkbox', 'fieldLabel' => 'Image Target', 'required' => false, 'description' => 'Designate as Image Target.', 'defaultValue' => false}], options[:options].merge({:checkbox_as_boolean => true}), @api_client, {})['defaultStore']
|
2187
|
+
default_stores << account_id
|
2188
|
+
end
|
2189
|
+
end
|
2167
2190
|
end
|
2168
2191
|
end
|
2169
2192
|
end
|
2170
2193
|
end
|
2171
|
-
|
2194
|
+
if options[:for_datastore]
|
2195
|
+
permissions['tenantPermissions'] = accounts.collect {|it| {'id' => it, 'defaultStore' => default_stores.include?(it), 'defaultTarget' => default_targets.include?(it)}}
|
2196
|
+
else
|
2197
|
+
permissions['tenantPermissions'] = {'accounts' => accounts}
|
2198
|
+
end
|
2172
2199
|
end
|
2173
2200
|
end
|
2174
2201
|
permissions
|
@@ -404,6 +404,9 @@ module Morpheus
|
|
404
404
|
value = password_prompt(option_type)
|
405
405
|
elsif option_type['type'] == 'checkbox'
|
406
406
|
value = checkbox_prompt(option_type)
|
407
|
+
if options[:checkbox_as_boolean]
|
408
|
+
value = (value == 'on')
|
409
|
+
end
|
407
410
|
elsif option_type['type'] == 'radio'
|
408
411
|
value = radio_prompt(option_type)
|
409
412
|
elsif option_type['type'] == 'textarea'
|
data/lib/morpheus/cli/version.rb
CHANGED
data/lib/morpheus/formatters.rb
CHANGED
@@ -478,6 +478,18 @@ def format_name_values(obj)
|
|
478
478
|
end
|
479
479
|
end
|
480
480
|
|
481
|
+
def format_name_and_id(obj)
|
482
|
+
if(obj.is_a?(Array))
|
483
|
+
return "" if obj.empty? # && hide_empty
|
484
|
+
names, ids = obj.collect {|it| it['name'] rescue "" }, obj.collect {|it| it['id'] rescue "" }
|
485
|
+
"#{names.join(", ")} [#{ids.join(",")}]"
|
486
|
+
elsif(obj.is_a?(Hash))
|
487
|
+
"#{obj['name']} [#{obj['id']}]" rescue ""
|
488
|
+
else
|
489
|
+
object.to_s
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
481
493
|
def a_or_an(v)
|
482
494
|
v.to_s =~ /^[aeiou]/i ? "an" : "a"
|
483
495
|
end
|
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:
|
4
|
+
version: 8.0.1
|
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-12-13 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: public_suffix
|
@@ -289,6 +289,7 @@ files:
|
|
289
289
|
- lib/morpheus/api/library_container_upgrades_interface.rb
|
290
290
|
- lib/morpheus/api/library_instance_types_interface.rb
|
291
291
|
- lib/morpheus/api/library_layouts_interface.rb
|
292
|
+
- lib/morpheus/api/library_operating_systems_interface.rb
|
292
293
|
- lib/morpheus/api/library_spec_template_types_interface.rb
|
293
294
|
- lib/morpheus/api/library_spec_templates_interface.rb
|
294
295
|
- lib/morpheus/api/license_interface.rb
|
@@ -473,6 +474,7 @@ files:
|
|
473
474
|
- lib/morpheus/cli/commands/library_forms_command.rb
|
474
475
|
- lib/morpheus/cli/commands/library_instance_types_command.rb
|
475
476
|
- lib/morpheus/cli/commands/library_layouts_command.rb
|
477
|
+
- lib/morpheus/cli/commands/library_operating_systems_command.rb
|
476
478
|
- lib/morpheus/cli/commands/library_option_lists_command.rb
|
477
479
|
- lib/morpheus/cli/commands/library_option_types_command.rb
|
478
480
|
- lib/morpheus/cli/commands/library_spec_templates_command.rb
|
@@ -667,7 +669,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
667
669
|
- !ruby/object:Gem::Version
|
668
670
|
version: '0'
|
669
671
|
requirements: []
|
670
|
-
rubygems_version: 3.
|
672
|
+
rubygems_version: 3.4.10
|
671
673
|
signing_key:
|
672
674
|
specification_version: 4
|
673
675
|
summary: Provides CLI Interface to the Morpheus Public/Private Cloud Appliance
|