morpheus-cli 5.5.3.2 → 6.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +8 -0
  4. data/lib/morpheus/api/cloud_resource_pools_interface.rb +28 -3
  5. data/lib/morpheus/api/containers_interface.rb +10 -0
  6. data/lib/morpheus/api/doc_interface.rb +1 -10
  7. data/lib/morpheus/api/jobs_interface.rb +2 -2
  8. data/lib/morpheus/api/key_pairs_interface.rb +9 -0
  9. data/lib/morpheus/api/network_floating_ips_interface.rb +37 -0
  10. data/lib/morpheus/api/resource_pool_groups_interface.rb +51 -0
  11. data/lib/morpheus/cli/cli_command.rb +17 -11
  12. data/lib/morpheus/cli/commands/appliance_settings_command.rb +5 -0
  13. data/lib/morpheus/cli/commands/apps.rb +12 -6
  14. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +44 -12
  15. data/lib/morpheus/cli/commands/clusters.rb +23 -2
  16. data/lib/morpheus/cli/commands/containers_command.rb +129 -4
  17. data/lib/morpheus/cli/commands/doc.rb +14 -13
  18. data/lib/morpheus/cli/commands/hosts.rb +2 -0
  19. data/lib/morpheus/cli/commands/instances.rb +9 -3
  20. data/lib/morpheus/cli/commands/jobs_command.rb +50 -3
  21. data/lib/morpheus/cli/commands/key_pairs.rb +94 -33
  22. data/lib/morpheus/cli/commands/network_floating_ips.rb +109 -0
  23. data/lib/morpheus/cli/commands/reports_command.rb +8 -1
  24. data/lib/morpheus/cli/commands/resource_pool_groups_command.rb +586 -0
  25. data/lib/morpheus/cli/commands/roles.rb +10 -10
  26. data/lib/morpheus/cli/commands/service_catalog_command.rb +40 -2
  27. data/lib/morpheus/cli/commands/service_plans_command.rb +51 -22
  28. data/lib/morpheus/cli/commands/shell.rb +1 -1
  29. data/lib/morpheus/cli/commands/tasks.rb +130 -35
  30. data/lib/morpheus/cli/commands/workflows.rb +109 -23
  31. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +148 -0
  32. data/lib/morpheus/cli/mixins/jobs_helper.rb +30 -3
  33. data/lib/morpheus/cli/mixins/processes_helper.rb +2 -26
  34. data/lib/morpheus/cli/mixins/provisioning_helper.rb +2 -1
  35. data/lib/morpheus/cli/option_types.rb +2 -2
  36. data/lib/morpheus/cli/version.rb +1 -1
  37. data/test/cli/doc_test.rb +1 -1
  38. metadata +6 -2
@@ -550,40 +550,101 @@ class Morpheus::Cli::Workflows
550
550
  target_type = nil
551
551
  instance_ids = []
552
552
  instances = []
553
+ instance_label = nil
553
554
  server_ids = []
554
555
  servers = []
555
- default_refresh_interval = 10
556
+ server_label = nil
557
+ default_refresh_interval = 5
558
+ all_target_types = ['appliance', 'instance', 'instance-label', 'server', 'server-label']
556
559
  optparse = Morpheus::Cli::OptionParser.new do |opts|
557
- opts.banner = subcommand_usage("[workflow] --instance [instance] [options]")
558
- opts.on('--instance INSTANCE', String, "Instance name or id to execute the workflow on. This option can be passed more than once.") do |val|
560
+ opts.banner = subcommand_usage("[workflow] [options]")
561
+ opts.on('--context-type VALUE', String, "Context Type, #{ored_list(all_target_types)}") do |val|
562
+ val = val.downcase
563
+ val = 'appliance' if val == 'none'
564
+ if target_type && target_type != val
565
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
566
+ end
567
+ if !all_target_types.include?(val)
568
+ raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
569
+ end
570
+ target_type = val
571
+ end
572
+ opts.on('--target-type VALUE', String, "alias for context-type") do |val|
573
+ val = val.downcase
574
+ val = 'appliance' if val == 'none'
575
+ if target_type && target_type != val
576
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
577
+ end
578
+ if !all_target_types.include?(val)
579
+ raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
580
+ end
581
+ target_type = val
582
+ end
583
+ opts.add_hidden_option('--target-type')
584
+ opts.on('--instance INSTANCE', String, "Instance name or id to target for execution. This option can be passed more than once.") do |val|
585
+ if target_type && target_type != 'instance'
586
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
587
+ end
559
588
  target_type = 'instance'
560
589
  instance_ids << val
561
590
  end
562
- opts.on('--instances [LIST]', Array, "Instances, comma separated list of instance names or IDs.") do |list|
591
+ opts.on('--instances LIST', Array, "Instances, comma separated list of instance names or IDs.") do |list|
592
+ if target_type && target_type != 'instance'
593
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
594
+ end
563
595
  target_type = 'instance'
564
596
  instance_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
565
597
  end
566
- opts.on('--host HOST', String, "Host name or id to execute the workflow on. This option can be passed more than once.") do |val|
598
+ opts.on('--instance-label LABEL', String, "Instance Label") do |val|
599
+ if target_type && target_type != 'instance-label'
600
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
601
+ end
602
+ target_type = 'instance-label'
603
+ instance_label = val
604
+ end
605
+ opts.on('--server SERVER', String, "Server name or id to target for execution. This option can be passed more than once.") do |val|
606
+ if target_type && target_type != 'server'
607
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
608
+ end
567
609
  target_type = 'server'
568
610
  server_ids << val
569
611
  end
570
- opts.on('--hosts [LIST]', Array, "Hosts, comma separated list of host names or IDs.") do |list|
612
+ opts.on('--servers LIST', Array, "Servers, comma separated list of host names or IDs.") do |list|
613
+ if target_type && target_type != 'server'
614
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
615
+ end
571
616
  target_type = 'server'
572
617
  server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
573
618
  end
574
- opts.on('--server HOST', String, "alias for --host") do |val|
619
+ opts.on('--server-label LABEL', String, "Server Label") do |val|
620
+ if target_type && target_type != 'server-label'
621
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
622
+ end
623
+ target_type = 'server-label'
624
+ server_label = val
625
+ end
626
+ opts.on('--host HOST', String, "alias for --server") do |val|
627
+ if target_type && target_type != 'server'
628
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
629
+ end
575
630
  target_type = 'server'
576
631
  server_ids << val
577
632
  end
578
- opts.on('--servers [LIST]', Array, "alias for --hosts") do |list|
633
+ opts.add_hidden_option('--host')
634
+ opts.on('--hosts HOSTS', Array, "alias for --servers") do |list|
635
+ if target_type && target_type != 'server'
636
+ raise ::OptionParser::InvalidOption.new("The --hosts option cannot be combined with another context (#{target_type})")
637
+ end
579
638
  target_type = 'server'
580
639
  server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
581
640
  end
641
+ opts.add_hidden_option('--hosts')
582
642
  opts.on('-a', '--appliance', "Execute on the appliance, the target is the appliance itself.") do
643
+ if target_type && target_type != 'appliance'
644
+ raise ::OptionParser::InvalidOption.new("The --appliance option cannot be combined with another context (#{target_type})")
645
+ end
583
646
  target_type = 'appliance'
584
647
  end
585
- opts.add_hidden_option('--server')
586
- opts.add_hidden_option('--servers')
587
648
  opts.on('--config [TEXT]', String, "Custom config") do |val|
588
649
  params['customConfig'] = val.to_s
589
650
  end
@@ -593,7 +654,7 @@ class Morpheus::Cli::Workflows
593
654
  opts.on(nil, '--no-refresh', "Do not refresh" ) do
594
655
  options[:no_refresh] = true
595
656
  end
596
- build_common_options(opts, options, [:payload, :options, :json, :dry_run, :remote])
657
+ build_standard_post_options(opts, options)
597
658
  end
598
659
  optparse.parse!(args)
599
660
  if args.count != 1
@@ -611,27 +672,55 @@ class Morpheus::Cli::Workflows
611
672
  payload = options[:payload]
612
673
  payload.deep_merge!({'job' => passed_options}) unless passed_options.empty?
613
674
  else
614
- if instance_ids.size > 0 && server_ids.size > 0
615
- raise_command_error "Pass --instance or --host, not both.\n#{optparse}"
616
- elsif instance_ids.size > 0
675
+ # prompt for target type and target
676
+ if target_type.nil?
677
+ # todo: Need api to fetch available Context Types for taskId/workflowId
678
+ available_target_types = get_available_contexts_for_workflow(workflow)
679
+ default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
680
+ if !available_target_types.empty?
681
+ default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
682
+ target_type = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'context-type', 'fieldName' => 'targetType', 'fieldLabel' => 'Context Type', 'type' => 'select', 'selectOptions' => available_target_types, 'defaultValue' => default_target_type, 'required' => true, 'description' => 'Context Type determines the type of target(s) for the execution'}], options[:options], @api_client)['targetType']
683
+ end
684
+ end
685
+ if target_type
686
+ params['targetType'] = target_type
687
+ end
688
+ if target_type == 'instance'
689
+ if instance_ids.empty?
690
+ instance_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instances', 'fieldName' => 'instances', 'fieldLabel' => 'Instance(s)', 'type' => 'text', 'required' => true, 'description' => 'Instances, comma separated list of instance names or IDs.'}], options[:options], @api_client)['instances']
691
+ instance_ids = parse_array(instance_ids_value)
692
+ end
617
693
  instance_ids.each do |instance_id|
618
694
  instance = find_instance_by_name_or_id(instance_id)
619
695
  return 1 if instance.nil?
620
696
  instances << instance
621
697
  end
622
698
  params['instances'] = instances.collect {|it| it['id'] }
623
- elsif server_ids.size > 0
699
+ elsif target_type == 'instance-label'
700
+ if instance_label.nil?
701
+ instance_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instance-label', 'fieldName' => 'instanceLabel', 'fieldLabel' => 'Instance Label', 'type' => 'text', 'required' => true, 'description' => 'Instance Label'}], options[:options], @api_client)['instanceLabel']
702
+ end
703
+ # params['config'] ||= {}
704
+ # params['config']['instanceLabel'] = instance_label
705
+ params['instanceLabel'] = instance_label
706
+ elsif target_type == 'server'
707
+ if server_ids.empty?
708
+ server_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'servers', 'fieldName' => 'servers', 'fieldLabel' => 'Server(s)', 'type' => 'text', 'required' => true, 'description' => 'Servers, comma separated list of server names or IDs.'}], options[:options], @api_client)['servers']
709
+ server_ids = parse_array(server_ids_value)
710
+ end
624
711
  server_ids.each do |server_id|
625
712
  server = find_server_by_name_or_id(server_id)
626
713
  return 1 if server.nil?
627
714
  servers << server
628
715
  end
629
716
  params['servers'] = servers.collect {|it| it['id'] }
630
- elsif target_type == 'appliance'
631
- # cool, run it locally.
632
- else
633
- # cool, run it locally.
634
- #raise_command_error "missing required option: --instance, --host or --appliance\n#{optparse}"
717
+ elsif target_type == 'server-label'
718
+ if server_label.nil?
719
+ server_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'server-label', 'fieldName' => 'serverLabel', 'fieldLabel' => 'Server Label', 'type' => 'text', 'required' => true, 'description' => 'Server Label'}], options[:options], @api_client)['serverLabel']
720
+ end
721
+ # params['config'] ||= {}
722
+ # params['config']['serverLabel'] = server_label
723
+ params['serverLabel'] = server_label
635
724
  end
636
725
 
637
726
  # prompt to workflow optionTypes for customOptions
@@ -643,9 +732,6 @@ class Morpheus::Cli::Workflows
643
732
  }
644
733
  custom_options = Morpheus::Cli::OptionTypes.prompt(custom_option_types, options[:options], @api_client, {})
645
734
  end
646
- if target_type
647
- params['targetType'] = target_type
648
- end
649
735
  job_payload = {}
650
736
  job_payload.deep_merge!(params)
651
737
  passed_options.delete('customOptions')
@@ -39,6 +39,18 @@ module Morpheus::Cli::InfrastructureHelper
39
39
  @network_groups_interface
40
40
  end
41
41
 
42
+ def resource_pool_groups_interface
43
+ # @api_client.resource_pool_groups
44
+ raise "#{self.class} has not defined @resource_pool_groups_interface" if @resource_pool_groups_interface.nil?
45
+ @resource_pool_groups_interface
46
+ end
47
+
48
+ def resource_pools_interface
49
+ # @api_client.resource_pool_groups
50
+ raise "#{self.class} has not defined @cloud_resource_pools_interface" if @cloud_resource_pools_interface.nil?
51
+ @cloud_resource_pools_interface
52
+ end
53
+
42
54
  def network_types_interface
43
55
  # @api_client.network_types
44
56
  raise "#{self.class} has not defined @network_types_interface" if @network_types_interface.nil?
@@ -343,6 +355,86 @@ module Morpheus::Cli::InfrastructureHelper
343
355
  end
344
356
  end
345
357
 
358
+ def find_resource_pool_by_name_or_id(val)
359
+ if val.to_s =~ /\A\d{1,}\Z/
360
+ return find_resource_pool_by_id(val)
361
+ else
362
+ return find_resource_pool_by_name(val)
363
+ end
364
+ end
365
+
366
+ def find_resource_pool_by_id(id)
367
+ begin
368
+ json_response = resource_pools_interface.get_without_cloud(id.to_i)
369
+ return json_response['resourcePool']
370
+ rescue RestClient::Exception => e
371
+ if e.response && e.response.code == 404
372
+ print_red_alert "Resource Pool not found by id #{id}"
373
+ return nil
374
+ else
375
+ raise e
376
+ end
377
+ end
378
+ end
379
+
380
+ def find_resource_pool_by_name(name)
381
+ json_response = resource_pools_interface.list_without_cloud({name: name.to_s})
382
+ resource_pools = json_response['resourcePools']
383
+ if resource_pools.empty?
384
+ print_red_alert "Resource Pool not found by name #{name}"
385
+ return nil
386
+ elsif resource_pools.size > 1
387
+ print_red_alert "#{resource_pools.size} resource pools found by name #{name}"
388
+ rows = resource_pools.collect do |it|
389
+ {id: it['id'], name: it['name']}
390
+ end
391
+ puts as_pretty_table(rows, [:id, :name], {color:red})
392
+ return nil
393
+ else
394
+ return resource_pools[0]
395
+ end
396
+ end
397
+
398
+ def find_resource_pool_group_by_name_or_id(val)
399
+ if val.to_s =~ /\A\d{1,}\Z/
400
+ return find_resource_pool_group_by_id(val)
401
+ else
402
+ return find_resource_pool_group_by_name(val)
403
+ end
404
+ end
405
+
406
+ def find_resource_pool_group_by_id(id)
407
+ begin
408
+ json_response = resource_pool_groups_interface.get(id.to_i)
409
+ return json_response['resourcePoolGroup']
410
+ rescue RestClient::Exception => e
411
+ if e.response && e.response.code == 404
412
+ print_red_alert "Resource Pool Group not found by id #{id}"
413
+ return nil
414
+ else
415
+ raise e
416
+ end
417
+ end
418
+ end
419
+
420
+ def find_resource_pool_group_by_name(name)
421
+ json_response = resource_pool_groups_interface.list({name: name.to_s})
422
+ resource_pool_groups = json_response['resourcePoolGroups']
423
+ if resource_pool_groups.empty?
424
+ print_red_alert "Resource Pool Group not found by name #{name}"
425
+ return nil
426
+ elsif resource_pool_groups.size > 1
427
+ print_red_alert "#{resource_pool_groups.size} resource pool groups found by name #{name}"
428
+ rows = resource_pool_groups.collect do |it|
429
+ {id: it['id'], name: it['name']}
430
+ end
431
+ puts as_pretty_table(rows, [:id, :name], {color:red})
432
+ return nil
433
+ else
434
+ return resource_pool_groups[0]
435
+ end
436
+ end
437
+
346
438
  def prompt_for_network(network_id, options={}, required=true, field_name='network', field_label='Network')
347
439
  # Prompt for a Network, text input that searches by name or id
348
440
  network = nil
@@ -479,6 +571,62 @@ module Morpheus::Cli::InfrastructureHelper
479
571
  return {success:true, data: record_ids}
480
572
  end
481
573
 
574
+ def prompt_for_pools(params, options={}, api_client=nil, api_params={})
575
+ # Pools
576
+ pool_list = nil
577
+ pool_ids = nil
578
+ still_prompting = true
579
+ if params['pools'].nil?
580
+ still_prompting = true
581
+ while still_prompting do
582
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pools', 'type' => 'text', 'fieldLabel' => 'Pools', 'required' => false, 'description' => 'Pools to include, comma separated list of names or IDs.'}], options[:options])
583
+ unless v_prompt['pools'].to_s.empty?
584
+ pool_list = v_prompt['pools'].split(",").collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
585
+ end
586
+ pool_ids = []
587
+ bad_ids = []
588
+ if pool_list && pool_list.size > 0
589
+ pool_list.each do |it|
590
+ found_pool = nil
591
+ begin
592
+ found_pool = find_resource_pool_by_name_or_id(it)
593
+ rescue SystemExit => cmdexit
594
+ end
595
+ if found_pool
596
+ pool_ids << found_pool['id']
597
+ else
598
+ bad_ids << it
599
+ end
600
+ end
601
+ end
602
+ still_prompting = bad_ids.empty? ? false : true
603
+ end
604
+ else
605
+ pool_list = params['pools']
606
+ still_prompting = false
607
+ pool_ids = []
608
+ bad_ids = []
609
+ if pool_list && pool_list.size > 0
610
+ pool_list.each do |it|
611
+ found_pool = nil
612
+ begin
613
+ found_pool = find_resource_pool_by_name_or_id(it)
614
+ rescue SystemExit => cmdexit
615
+ end
616
+ if found_pool
617
+ pool_ids << found_pool['id']
618
+ else
619
+ bad_ids << it
620
+ end
621
+ end
622
+ end
623
+ if !bad_ids.empty?
624
+ return {success:false, msg:"Pools not found: #{bad_ids}"}
625
+ end
626
+ end
627
+ return {success:true, data: pool_ids}
628
+ end
629
+
482
630
  def network_pool_server_list_column_definitions(options)
483
631
  {
484
632
  "ID" => 'id',
@@ -41,8 +41,8 @@ module Morpheus::Cli::JobsHelper
41
41
  "Created By" => lambda {|it| it[:created_by]},
42
42
  "Duration" => lambda {|it| it[:duration]},
43
43
  "Status" => lambda {|it| it[:status]},
44
- "Error" => lambda {|it| options[:details] ? it[:error] : truncate_string(it[:error], 32) },
45
- "Output" => lambda {|it| options[:details] ? it[:output] : truncate_string(it[:output], 32) }
44
+ "Error" => lambda {|it| options[:details] ? it[:error].to_s.strip : truncate_string(it[:error], 32).to_s.strip.gsub("\n", ' ') },
45
+ "Output" => lambda {|it| options[:details] ? it[:output].to_s.strip : truncate_string(it[:output], 32).to_s.strip.gsub("\n", ' ') }
46
46
  }
47
47
  print as_pretty_table(events.collect {|it| get_process_event_data(it)}, event_columns.upcase_keys!, options)
48
48
  end
@@ -147,7 +147,7 @@ module Morpheus::Cli::JobsHelper
147
147
  # refresh execution request until it is finished
148
148
  # returns json response data of the last execution request when status reached 'completed' or 'failed'
149
149
  def wait_for_job_execution(job_execution_id, options={}, print_output = true)
150
- refresh_interval = 10
150
+ refresh_interval = 5
151
151
  if options[:refresh_interval].to_i > 0
152
152
  refresh_interval = options[:refresh_interval]
153
153
  end
@@ -168,5 +168,32 @@ module Morpheus::Cli::JobsHelper
168
168
  end
169
169
 
170
170
 
171
+ def get_available_contexts_for_task(task)
172
+ #If task has target of resource, then CAN NOT run it local
173
+ targets = []
174
+ has_resource = task['executeTarget'] == 'resource'
175
+ if !has_resource
176
+ targets << {'name' => 'None', 'value' => 'appliance'}
177
+ end
178
+ targets << {'name' => 'Instance', 'value' => 'instance'}
179
+ targets << {'name' => 'Instance Label', 'value' => 'instance-label'}
180
+ targets << {'name' => 'Server', 'value' => 'server'}
181
+ targets << {'name' => 'Server Label', 'value' => 'server-label'}
182
+ return targets
183
+ end
184
+
185
+ def get_available_contexts_for_workflow(workflow)
186
+ #If any task has target of resource, then CAN NOT run it local
187
+ targets = []
188
+ has_resource = workflow['taskSetTasks'].find {|task| task['executeTarget'] == 'resource' }
189
+ if !has_resource
190
+ targets << {'name' => 'None', 'value' => 'appliance'}
191
+ end
192
+ targets << {'name' => 'Instance', 'value' => 'instance'}
193
+ targets << {'name' => 'Instance Label', 'value' => 'instance-label'}
194
+ targets << {'name' => 'Server', 'value' => 'server'}
195
+ targets << {'name' => 'Server Label', 'value' => 'server-label'}
196
+ return targets
197
+ end
171
198
 
172
199
  end
@@ -88,36 +88,12 @@ module Morpheus::Cli::ProcessesHelper
88
88
 
89
89
  # decolorize, remove newlines and truncate for table cell
90
90
  def format_process_error(process, max_length=20, return_color=cyan)
91
- #return max_length ? truncate_string(process['error'], max_length) : process['error']
92
- out = ""
93
- if process['error']
94
- # lines = process['error'].split("\n").collect {|line| reset + "#{line.to_s.strip}" }
95
- # lines = process['error'].split("\n").collect {|line| "#{line.to_s.strip}" }
96
- lines = [process['error']]
97
- out = lines.join(" ")
98
- if max_length
99
- out = truncate_string(out, max_length)
100
- end
101
- out << return_color if return_color
102
- end
103
- out
91
+ truncate_string(process['error'].to_s.strip.gsub("\n", " "), max_length)
104
92
  end
105
93
 
106
94
  # decolorize, remove newlines and truncate for table cell
107
95
  def format_process_output(process, max_length=20, return_color=cyan)
108
- return max_length ? truncate_string(process['output'], max_length) : process['output']
109
- out = ""
110
- if process['output']
111
- # lines = process['output'].split("\n").collect {|line| reset + "#{line.to_s.strip}" }
112
- # lines = process['error'].split("\n").collect {|line| "#{line.to_s.strip}" }
113
- lines = [process['output']]
114
- out = lines.join(" ")
115
- if max_length
116
- out = truncate_string(out, max_length)
117
- end
118
- out << return_color if return_color
119
- end
120
- out
96
+ truncate_string(process['output'].to_s.strip.gsub("\n", " "), max_length)
121
97
  end
122
98
 
123
99
  # format for either ETA/Duration
@@ -778,6 +778,7 @@ module Morpheus::Cli::ProvisioningHelper
778
778
 
779
779
  resource_pool_options = options_interface.options_for_source('zonePools', {groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], layoutId: layout["id"]}.merge(service_plan.nil? ? {} : {planId: service_plan["id"]}))['data']
780
780
  resource_pool = resource_pool_options.find {|opt| opt['id'] == options[:resource_pool].to_i} if options[:resource_pool]
781
+ pool_required = provision_type["zonePoolRequired"]
781
782
 
782
783
  if resource_pool
783
784
  pool_id = resource_pool['id']
@@ -785,7 +786,7 @@ module Morpheus::Cli::ProvisioningHelper
785
786
  if options[:default_resource_pool]
786
787
  default_resource_pool = resource_pool_options.find {|rp| rp['id'] == options[:default_resource_pool]}
787
788
  end
788
- resource_pool_option_type ||= {'fieldContext' => 'config', 'fieldName' => 'resourcePoolId', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'selectOptions' => resource_pool_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Select resource pool.', 'defaultValue' => default_resource_pool ? default_resource_pool['name'] : nil}
789
+ resource_pool_option_type ||= {'fieldContext' => 'config', 'fieldName' => 'resourcePoolId', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'selectOptions' => resource_pool_options, 'required' => pool_required, 'skipSingleOption' => true, 'description' => 'Select resource pool.', 'defaultValue' => default_resource_pool ? default_resource_pool['name'] : nil}
789
790
  resource_pool_prompt = Morpheus::Cli::OptionTypes.prompt([resource_pool_option_type],options[:options],api_client,{}, no_prompt, true)
790
791
  resource_pool_prompt.deep_compact!
791
792
  payload.deep_merge!(resource_pool_prompt)
@@ -678,7 +678,7 @@ module Morpheus
678
678
  # print "Perhaps you meant one of these? #{ored_list(matched_options.collect {|i|i[value_field]}, 3)}\n"
679
679
  print "Try using value instead of name.\n"
680
680
  print "\n"
681
- exit 1
681
+ #exit 1
682
682
  elsif matched_options.size == 1
683
683
  matched_option = matched_options[0]
684
684
  end
@@ -814,7 +814,7 @@ module Morpheus
814
814
  api_params ||= {}
815
815
  api_params['query'] = query_value
816
816
  # skip refresh if you just hit enter
817
- if !query_value.empty?
817
+ if !query_value.empty? || (select_options.nil? || select_options.empty?)
818
818
  select_options = load_options(option_type, api_client, api_params, query_value)
819
819
  end
820
820
 
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "5.5.3.2"
4
+ VERSION = "6.0.1"
5
5
  end
6
6
  end
data/test/cli/doc_test.rb CHANGED
@@ -28,7 +28,7 @@ class MorpheusTest::DocTest < MorpheusTest::TestCase
28
28
  def test_doc_get_unauthorized
29
29
  # authentication is NOT required for this api
30
30
  without_authentication do
31
- assert_success("doc get -q")
31
+ assert_error("doc get -q")
32
32
  end
33
33
  end
34
34
 
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: 5.5.3.2
4
+ version: 6.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: 2023-02-21 00:00:00.000000000 Z
14
+ date: 2023-03-14 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -280,6 +280,7 @@ files:
280
280
  - lib/morpheus/api/network_domain_records_interface.rb
281
281
  - lib/morpheus/api/network_domains_interface.rb
282
282
  - lib/morpheus/api/network_edge_clusters_interface.rb
283
+ - lib/morpheus/api/network_floating_ips_interface.rb
283
284
  - lib/morpheus/api/network_groups_interface.rb
284
285
  - lib/morpheus/api/network_pool_ips_interface.rb
285
286
  - lib/morpheus/api/network_pool_server_types_interface.rb
@@ -313,6 +314,7 @@ files:
313
314
  - lib/morpheus/api/provisioning_settings_interface.rb
314
315
  - lib/morpheus/api/read_interface.rb
315
316
  - lib/morpheus/api/reports_interface.rb
317
+ - lib/morpheus/api/resource_pool_groups_interface.rb
316
318
  - lib/morpheus/api/rest_interface.rb
317
319
  - lib/morpheus/api/roles_interface.rb
318
320
  - lib/morpheus/api/scale_thresholds_interface.rb
@@ -455,6 +457,7 @@ files:
455
457
  - lib/morpheus/cli/commands/network_domains_command.rb
456
458
  - lib/morpheus/cli/commands/network_edge_clusters_command.rb
457
459
  - lib/morpheus/cli/commands/network_firewalls_command.rb
460
+ - lib/morpheus/cli/commands/network_floating_ips.rb
458
461
  - lib/morpheus/cli/commands/network_groups_command.rb
459
462
  - lib/morpheus/cli/commands/network_pool_server_types.rb
460
463
  - lib/morpheus/cli/commands/network_pool_servers_command.rb
@@ -483,6 +486,7 @@ files:
483
486
  - lib/morpheus/cli/commands/recent_activity_command.rb
484
487
  - lib/morpheus/cli/commands/remote.rb
485
488
  - lib/morpheus/cli/commands/reports_command.rb
489
+ - lib/morpheus/cli/commands/resource_pool_groups_command.rb
486
490
  - lib/morpheus/cli/commands/rm_command.rb
487
491
  - lib/morpheus/cli/commands/roles.rb
488
492
  - lib/morpheus/cli/commands/scale_thresholds.rb