morpheus-cli 7.0.7 → 8.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 + "MVM 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"
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
- return 9, "aborted command"
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
- if hubmode == 'skip'
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.install([] + (options[:remote] ? ["-r",options[:remote]] : []))
389
- # license_is_valid = cmd_res != false
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
- if ::Morpheus::Cli::OptionTypes::confirm("Would you like to create the first group now?", options.merge({:default => true}))
394
- cmd_res = Morpheus::Cli::Groups.new.add(['--use'] + (options[:remote] ? ["-r",options[:remote]] : []))
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
- #print "\n"
409
+ #print "\n"
397
410
 
398
- # if cmd_res !=
399
- if ::Morpheus::Cli::OptionTypes::confirm("Would you like to create the first cloud now?", options.merge({:default => true}))
400
- cmd_res = Morpheus::Cli::Clouds.new.add([] + (options[:remote] ? ["-r",options[:remote]] : []))
401
- #print "\n"
402
- end
403
- # end
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("[name] [options]")
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
- "[name] is required. This is the name or id of a virtual image."
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("[name] [filepath]")
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
- "[name] is required. This is the name or id of a virtual image." + "\n" +
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("[name] [filename]")
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' => 'Storage Provider', 'optionSource' => 'storageProviders', 'required' => false, 'description' => 'Select Storage Provider.', 'displayOrder' => 9},
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 << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageFile', 'fieldLabel' => 'Image File', 'type' => 'file', 'required' => false, 'description' => 'Choose an image file to upload', 'displayOrder' => 11}
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.to_i == 0
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 = ((used_value.nil? || max_value.to_f == 0.0) ? unlimited_label : "#{percent.round(percent_sigdig)}%").rjust(6, ' ')
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 name_prompt['name'].nil? && !options[:name_required]
511
+ name = name_prompt['name']
512
+ if name.nil? && !options[:name_required]
513
513
  break
514
514
  else
515
- if instances_interface.list({name: name_prompt['name']})['instances'].empty?
516
- instance_name = name_prompt['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] == name_prompt['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
- if !account_id.nil?
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
- permissions['tenantPermissions'] = {'accounts' => accounts}
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'
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "7.0.7"
4
+ VERSION = "8.0.1"
5
5
  end
6
6
  end
@@ -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: 7.0.7
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-10-14 00:00:00.000000000 Z
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.1.6
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