morpheus-cli 7.0.6 → 8.0.0

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.
@@ -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"
@@ -16,7 +16,7 @@ class Morpheus::Cli::PluginsCommand
16
16
  params = {}
17
17
  filename = nil
18
18
  optparse = Morpheus::Cli::OptionParser.new do|opts|
19
- opts.banner = subcommand_usage("[name] [file]")
19
+ opts.banner = subcommand_usage("[file]")
20
20
  build_standard_post_options(opts, options)
21
21
  opts.footer = <<-EOT
22
22
  Upload a plugin file.
@@ -55,7 +55,7 @@ EOT
55
55
  params = {}
56
56
  filename = nil
57
57
  optparse = Morpheus::Cli::OptionParser.new do|opts|
58
- opts.banner = subcommand_usage("[name] [file]")
58
+ opts.banner = subcommand_usage("")
59
59
  build_standard_post_options(opts, options)
60
60
  opts.footer = <<-EOT
61
61
  Check for installed plugins that have available updates.
@@ -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
@@ -531,6 +531,7 @@ EOT
531
531
  v_prompt.deep_compact!
532
532
  virtual_image_payload.deep_merge!(v_prompt)
533
533
  virtual_image_files = virtual_image_payload.delete('virtualImageFiles')
534
+ upload_type = virtual_image_payload.delete('uploadType') # not used serverside
534
535
  virtual_image_payload['imageType'] = image_type['code']
535
536
  storage_provider_id = virtual_image_payload.delete('storageProviderId')
536
537
  if !storage_provider_id.to_s.empty?
@@ -551,6 +552,11 @@ EOT
551
552
  if virtual_image_payload && virtual_image_payload['imageType'] == 'vmware'
552
553
  virtual_image_payload['imageType'] == 'vmdk'
553
554
  end
555
+ # no need to make second request anymore, just include virtualImage.url
556
+ if file_url
557
+ virtual_image_payload['url'] = file_url
558
+ file_url = nil
559
+ end
554
560
  #payload = {'virtualImage' => virtual_image_payload}
555
561
  payload.deep_merge!({'virtualImage' => virtual_image_payload})
556
562
  end
@@ -967,7 +973,7 @@ EOT
967
973
  {'fieldName' => 'installAgent', 'fieldLabel' => 'Install Agent?', 'type' => 'checkbox', 'defaultValue' => 'off', 'required' => false, 'description' => 'Install Agent?', 'displayOrder' => 6},
968
974
  {'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text', 'required' => false, 'description' => 'Enter an SSH Username', 'displayOrder' => 7},
969
975
  {'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},
976
+ {'fieldName' => 'storageProviderId', 'type' => 'select', 'fieldLabel' => 'Bucket', 'optionSource' => 'storageProviders', 'required' => false, 'description' => 'Select Storage Provider.', 'displayOrder' => 9},
971
977
  {'fieldName' => 'userData', 'fieldLabel' => 'Cloud-Init User Data', 'type' => 'textarea', 'required' => false, 'displayOrder' => 10},
972
978
  {'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
979
  {'fieldName' => 'isAutoJoinDomain', 'fieldLabel' => 'Auto Join Domain?', 'type' => 'checkbox', 'defaultValue' => 'off', 'required' => false, 'description' => 'Auto Join Domain?', 'category' => 'advanced', 'displayOrder' => 40},
@@ -999,7 +1005,9 @@ EOT
999
1005
  tmp_option_types.reject! {|opt| ['storageProviderId', 'userData', 'sshUsername', 'sshPassword'].include?(opt['fieldName'])}
1000
1006
  else
1001
1007
  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}
1008
+ 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}
1009
+ 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}
1010
+ 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
1011
  end
1004
1012
  end
1005
1013
  end
@@ -2150,25 +2150,51 @@ module Morpheus::Cli::ProvisioningHelper
2150
2150
  end
2151
2151
 
2152
2152
  # Tenants
2153
+ default_stores = []
2154
+ default_targets = []
2153
2155
  unless excludes.include?('tenants')
2154
2156
  if !options[:tenants].nil?
2155
2157
  accounts = options[:tenants].collect {|id| id.to_i}
2156
2158
  elsif !options[:no_prompt]
2157
2159
  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
2160
 
2159
- if !account_id.nil?
2161
+ unless account_id.nil?
2160
2162
  accounts << account_id
2161
2163
  available_accounts = available_accounts.reject {|it| it['value'] == account_id}
2162
2164
 
2165
+ # Prompt default store / target
2166
+ if options[:for_datastore]
2167
+ 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']
2168
+ default_targets << account_id
2169
+ end
2170
+ 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']
2171
+ default_stores << account_id
2172
+ end
2173
+ end
2174
+
2163
2175
  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
2176
  if !account_id.nil?
2165
2177
  accounts << account_id
2166
2178
  available_accounts = available_accounts.reject {|it| it['value'] == account_id}
2179
+
2180
+ # Prompt default store / target
2181
+ if options[:for_datastore]
2182
+ 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']
2183
+ default_targets << account_id
2184
+ end
2185
+ 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']
2186
+ default_stores << account_id
2187
+ end
2188
+ end
2167
2189
  end
2168
2190
  end
2169
2191
  end
2170
2192
  end
2171
- permissions['tenantPermissions'] = {'accounts' => accounts}
2193
+ if options[:for_datastore]
2194
+ permissions['tenantPermissions'] = accounts.collect {|it| {'id' => it, 'defaultStore' => default_stores.include?(it), 'defaultTarget' => default_targets.include?(it)}}
2195
+ else
2196
+ permissions['tenantPermissions'] = {'accounts' => accounts}
2197
+ end
2172
2198
  end
2173
2199
  end
2174
2200
  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'
@@ -1324,15 +1327,19 @@ module Morpheus
1324
1327
 
1325
1328
  # supports multi-part fields via config.fields
1326
1329
  # {"fields": [{"name":"tag", "required":true, "label": "Tag"}, {"name":"value", "required":false, "label": "Scope"}]}
1330
+ min_count = option_type['minCount'] || 1
1331
+ count = 0
1332
+
1327
1333
  if option_type['config']['fields']
1328
- while (option_type['required'] && rtn.empty?) || self.confirm("Add#{rtn.empty? ? '': ' more'} #{option_type['fieldLabel']}?", {:default => false})
1334
+ while (option_type['required'] && (rtn.empty? || count < min_count)) || self.confirm("Add#{rtn.empty? ? '': ' more'} #{option_type['fieldLabel']}?", {:default => false})
1329
1335
  rtn ||= []
1330
1336
  value = {}
1331
1337
  option_type['config']['fields'].each do |field|
1332
1338
  field_label = field['label'] || field['name'].capitalize
1333
- value[field['name']] = generic_prompt(option_type.merge({'fieldLabel' => field_label, 'required' => field['required'], 'description' => "#{option_type['fieldLabel']} #{field_label}"}))
1339
+ value[field['name']] = generic_prompt(option_type.merge({'fieldLabel' => min_count > 1 ? "#{field_label} #{count + 1}" : field_label, 'required' => field['required'], 'description' => "#{option_type['fieldLabel']} #{field_label}"}))
1334
1340
  end
1335
1341
  rtn << value
1342
+ count += 1
1336
1343
  end
1337
1344
  else
1338
1345
  if rtn = generic_prompt(option_type)
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "7.0.6"
4
+ VERSION = "8.0.0"
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.6
4
+ version: 8.0.0
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-09-11 00:00:00.000000000 Z
14
+ date: 2024-11-15 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