morpheus-cli 5.3.2.1 → 5.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +12 -0
  4. data/lib/morpheus/api/clouds_interface.rb +4 -11
  5. data/lib/morpheus/api/instances_interface.rb +18 -5
  6. data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
  7. data/lib/morpheus/api/load_balancer_profiles_interface.rb +10 -0
  8. data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +4 -4
  9. data/lib/morpheus/api/network_routers_interface.rb +21 -0
  10. data/lib/morpheus/api/network_servers_interface.rb +42 -0
  11. data/lib/morpheus/api/rest_interface.rb +2 -1
  12. data/lib/morpheus/api/virtual_images_interface.rb +23 -2
  13. data/lib/morpheus/api/virtual_servers_interface.rb +9 -0
  14. data/lib/morpheus/cli/apps.rb +3 -2
  15. data/lib/morpheus/cli/cli_command.rb +14 -6
  16. data/lib/morpheus/cli/cli_registry.rb +55 -2
  17. data/lib/morpheus/cli/cloud_resource_pools_command.rb +170 -134
  18. data/lib/morpheus/cli/clouds.rb +22 -40
  19. data/lib/morpheus/cli/clusters.rb +51 -33
  20. data/lib/morpheus/cli/hosts.rb +0 -1
  21. data/lib/morpheus/cli/instances.rb +372 -150
  22. data/lib/morpheus/cli/invoices_command.rb +117 -133
  23. data/lib/morpheus/cli/library_cluster_layouts_command.rb +20 -0
  24. data/lib/morpheus/cli/library_option_lists_command.rb +3 -3
  25. data/lib/morpheus/cli/load_balancer_pools.rb +111 -0
  26. data/lib/morpheus/cli/load_balancer_virtual_servers.rb +136 -0
  27. data/lib/morpheus/cli/load_balancers.rb +0 -155
  28. data/lib/morpheus/cli/mixins/load_balancers_helper.rb +2 -2
  29. data/lib/morpheus/cli/mixins/provisioning_helper.rb +155 -112
  30. data/lib/morpheus/cli/mixins/rest_command.rb +53 -37
  31. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +488 -0
  32. data/lib/morpheus/cli/monitoring_checks_command.rb +2 -0
  33. data/lib/morpheus/cli/network_routers_command.rb +291 -7
  34. data/lib/morpheus/cli/network_scopes_command.rb +442 -0
  35. data/lib/morpheus/cli/networks_command.rb +3 -3
  36. data/lib/morpheus/cli/option_parser.rb +25 -17
  37. data/lib/morpheus/cli/option_types.rb +42 -15
  38. data/lib/morpheus/cli/subnets_command.rb +7 -2
  39. data/lib/morpheus/cli/tasks.rb +25 -2
  40. data/lib/morpheus/cli/vdi_pools_command.rb +4 -1
  41. data/lib/morpheus/cli/version.rb +1 -1
  42. data/lib/morpheus/cli/virtual_images.rb +251 -29
  43. data/lib/morpheus/cli.rb +9 -1
  44. data/morpheus-cli.gemspec +1 -1
  45. metadata +11 -4
@@ -198,7 +198,14 @@ class Morpheus::Cli::Tasks
198
198
  end
199
199
  else
200
200
  task_option_types << optionType
201
- task_option_columns << {(optionType['fieldLabel']) => lambda {|it| task['taskOptions'][optionType['fieldName']] || optionType['defaultValue'] } }
201
+ task_option_columns << {(optionType['fieldLabel']) => lambda {|it|
202
+ value = task['taskOptions'][optionType['code']] || task['taskOptions'][optionType['fieldName']] || optionType['defaultValue']
203
+ if optionType['type'] == 'checkbox'
204
+ value.to_s.empty? ? 'off' : value.to_s
205
+ else
206
+ value.to_s
207
+ end
208
+ } }
202
209
  end
203
210
  end
204
211
  else
@@ -430,6 +437,10 @@ class Morpheus::Cli::Tasks
430
437
  if it['fieldContext'].nil? || it['fieldContext'] == ''
431
438
  it['fieldContext'] = 'taskOptions'
432
439
  end
440
+ # taskOptions should prompt for code instead of fieldName, oy vey
441
+ if it['fieldContext'] == 'taskOptions'
442
+ it['fieldName'] = it['code']
443
+ end
433
444
  end
434
445
  end
435
446
  # inject file_params into options for file-content prompt
@@ -444,8 +455,20 @@ class Morpheus::Cli::Tasks
444
455
  end
445
456
  end
446
457
  # prompt
458
+
459
+ # tasks are different in that they use the optionType code instead of fieldName for the key values
447
460
  input_options = Morpheus::Cli::OptionTypes.prompt(task_option_types, options[:options],@api_client, options[:params])
448
- payload.deep_merge!({'task' => input_options}) unless input_options.empty?
461
+ # flatten taskOptions as serverside expects
462
+ if input_options['taskOptions']
463
+ input_options['taskOptions'] = Morpheus::RestClient.grails_params(input_options['taskOptions'])
464
+ # remove "off" checkbox values, like the UI does
465
+ input_options['taskOptions'].keys.each do |k|
466
+ if input_options['taskOptions'][k] == "off"
467
+ input_options['taskOptions'].delete(k)
468
+ end
469
+ end
470
+ end
471
+ payload.deep_merge!({'task' => input_options}) unless input_options.empty?
449
472
 
450
473
 
451
474
  # Target Options
@@ -418,6 +418,7 @@ EOT
418
418
  "Name" => 'name',
419
419
  "Description" => 'description',
420
420
  "Persistent" => lambda {|it| format_boolean(it['persistentUser']) },
421
+ "Recyclable" => lambda {|it| it['recyclable'].nil? ? nil : format_boolean(it['recyclable']) },
421
422
  "Enabled" => lambda {|it| format_boolean(it['enabled']) },
422
423
  "Pool Usage" => lambda {|it|
423
424
  # todo: [== ] 2/8 would be neat generate_usage_bar(...)
@@ -447,12 +448,13 @@ EOT
447
448
  "Max Size" => lambda {|it| format_number(it['maxPoolSize']) rescue '' },
448
449
  "Lease Timeout" => lambda {|it| format_number(it['allocationTimeoutMinutes']) rescue '' },
449
450
  "Persistent" => lambda {|it| format_boolean(it['persistentUser']) },
451
+ "Recyclable" => lambda {|it| it['recyclable'].nil? ? nil : format_boolean(it['recyclable']) },
452
+ "Enabled" => lambda {|it| format_boolean(it['enabled']) },
450
453
  "Allow Copy" => lambda {|it| format_boolean(it['allowCopy']) },
451
454
  "Allow Printer" => lambda {|it| format_boolean(it['allowPrinter']) },
452
455
  "Allow File Share" => lambda {|it| format_boolean(it['allowFileshare']) },
453
456
  "Allow Hypervisor Console" => lambda {|it| format_boolean(it['allowHypervisorConsole']) },
454
457
  "Auto Create User" => lambda {|it| format_boolean(it['autoCreateLocalUserOnReservation']) },
455
- "Enabled" => lambda {|it| format_boolean(it['enabled']) },
456
458
  "Logo" => lambda {|it| it['logo'] || it['imagePath'] },
457
459
  #"Config" => lambda {|it| it['config'] },
458
460
  "Group" => lambda {|it| it['group'] ? it['group']['name'] : nil },
@@ -484,6 +486,7 @@ EOT
484
486
  {'fieldName' => 'maxPoolSize', 'fieldLabel' => 'Max Size', 'type' => 'number', 'required' => true, 'description' => 'Max limit on number of allocations and instances within the pool.'},
485
487
  {'fieldName' => 'allocationTimeoutMinutes', 'fieldLabel' => 'Lease Timeout', 'type' => 'number', 'description' => 'Time (in minutes) after a user disconnects before an allocation is recycled or shutdown depending on persistence.'},
486
488
  {'fieldName' => 'persistentUser', 'fieldLabel' => 'Persistent', 'type' => 'checkbox', 'defaultValue' => false},
489
+ {'fieldName' => 'recyclable', 'fieldLabel' => 'Recyclable', 'type' => 'checkbox', 'defaultValue' => false, 'description' => 'Recyclable VDI Pools only work with cloud types that support snapshot management (i.e. Vmware, Nutanix, VCD)'},
487
490
  {'fieldName' => 'allowCopy', 'fieldLabel' => 'Allow Copy', 'type' => 'checkbox', 'defaultValue' => false},
488
491
  {'fieldName' => 'allowPrinter', 'fieldLabel' => 'Allow Printer', 'type' => 'checkbox', 'defaultValue' => false},
489
492
  {'fieldName' => 'allowFileshare', 'fieldLabel' => 'Allow File Share', 'type' => 'checkbox', 'defaultValue' => false},
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "5.3.2.1"
4
+ VERSION = "5.3.4"
5
5
  end
6
6
  end
@@ -11,8 +11,7 @@ class Morpheus::Cli::VirtualImages
11
11
  include Morpheus::Cli::ProvisioningHelper
12
12
 
13
13
  register_subcommands :list, :get, :add, :add_file, :remove_file, :update, :remove, :types => :virtual_image_types
14
- alias_subcommand :details, :get
15
- set_default_subcommand :list
14
+ register_subcommands :list_locations, :get_location, :remove_location
16
15
 
17
16
  # def initialize()
18
17
  # # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
@@ -84,6 +83,7 @@ class Morpheus::Cli::VirtualImages
84
83
  json_response = @virtual_images_interface.list(params)
85
84
  images = json_response['virtualImages']
86
85
  render_response(json_response, options, 'virtualImages') do
86
+ get_available_virtual_image_types() # preload
87
87
  title = "Morpheus Virtual Images"
88
88
  subtitles = parse_list_subtitles(options)
89
89
  if options[:imageType]
@@ -188,10 +188,12 @@ EOT
188
188
  image = json_response['virtualImage']
189
189
  image_config = image['config'] || {}
190
190
  image_volumes = image['volumes'] || []
191
+ image_locations = image['locations'] || []
191
192
  image_files = json_response['cloudFiles'] || json_response['files']
192
193
  image_type = virtual_image_type_for_name_or_code(image['imageType'])
193
194
  image_type_display = image_type ? "#{image_type['name']}" : image['imageType']
194
195
  render_response(json_response, options, 'virtualImage') do
196
+ get_available_virtual_image_types() # preload
195
197
  print_h1 "Virtual Image Details", [], options
196
198
  description_cols = {
197
199
  "ID" => 'id',
@@ -255,7 +257,7 @@ EOT
255
257
  # print "\n", reset
256
258
  end
257
259
 
258
- if image_files
260
+ if image_files && !image_files.empty?
259
261
  print_h2 "Files (#{image_files.size})"
260
262
  # image_files.each {|image_file|
261
263
  # pretty_filesize = Filesize.from("#{image_file['size']} B").pretty
@@ -270,6 +272,11 @@ EOT
270
272
  print as_pretty_table(image_file_rows, [:filename, :size])
271
273
  # print reset,"\n"
272
274
  end
275
+
276
+ if image_locations && !image_locations.empty?
277
+ print_h2 "Locations", options
278
+ print as_pretty_table(image_locations, virtual_image_location_list_column_definitions.upcase_keys!, options)
279
+ end
273
280
 
274
281
  if options[:details] && image_config && !image_config.empty?
275
282
  print_h2 "Config", options
@@ -689,7 +696,7 @@ EOT
689
696
  image = find_virtual_image_by_name_or_id(image_name)
690
697
  return 1 if image.nil?
691
698
  unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image filename #{filename}?")
692
- exit
699
+ return 9, "aborted"
693
700
  end
694
701
  @virtual_images_interface.setopts(options)
695
702
  if options[:dry_run]
@@ -709,44 +716,188 @@ EOT
709
716
  end
710
717
 
711
718
  def remove(args)
719
+ params = {}
712
720
  options = {}
713
721
  optparse = Morpheus::Cli::OptionParser.new do |opts|
714
- opts.banner = subcommand_usage("[name]")
715
- build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
722
+ opts.banner = subcommand_usage("[image] [location]")
723
+ opts.on('--remove-from-cloud [true|false]', String, "Remove from all clouds. Default is true.") do |val|
724
+ options[:options]['removeFromCloud'] = ['','true','on'].include?(val.to_s)
725
+ end
726
+ build_standard_remove_options(opts, options)
727
+ opts.footer = <<-EOT
728
+ Delete a virtual image.
729
+ [image] is required. This is the name or id of a virtual image.
730
+ EOT
716
731
  end
717
732
  optparse.parse!(args)
718
- if args.count < 1
719
- puts optparse
720
- exit 1
733
+ verify_args!(args:args, optparse:optparse, count:1)
734
+ connect(options)
735
+ image = find_virtual_image_by_name_or_id(args[0])
736
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
737
+ params.merge!(parse_query_options(options))
738
+ # Delete prompt
739
+ # [ X ] Remove from all clouds
740
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'removeFromCloud', 'fieldLabel' => 'Remove from all clouds', 'type' => 'checkbox', 'defaultValue' => true, 'required' => true, 'description' => "Remove from all clouds"}], options[:options], @api_client)
741
+ remove_from_cloud = v_prompt['removeFromCloud'].to_s == 'true' || v_prompt['removeFromCloud'].to_s == 'on'
742
+ params['removeFromCloud'] = remove_from_cloud
743
+
744
+ # Delete confirmation
745
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image #{image['name']}?")
746
+ return 9, "aborted"
747
+ end
748
+
749
+ @virtual_images_interface.setopts(options)
750
+ if options[:dry_run]
751
+ print_dry_run @virtual_images_interface.dry.destroy(image['id'], params)
752
+ return
753
+ end
754
+ json_response = @virtual_images_interface.destroy(image['id'], params)
755
+ render_response(json_response, options) do
756
+ print_green_success "Removed virtual image #{image['name']}"
757
+ end
758
+ return 0, nil
759
+ end
760
+
761
+ def list_locations(args)
762
+ params = {}
763
+ options = {}
764
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
765
+ opts.banner = subcommand_usage("[image]")
766
+ build_standard_list_options(opts, options)
767
+ opts.footer = <<-EOT
768
+ List virtual image locations for a specific virtual image.
769
+ [image] is required. This is the name or id of a virtual image.
770
+ EOT
771
+ end
772
+ optparse.parse!(args)
773
+ verify_args!(args:args, optparse:optparse, min:1)
774
+ if args.count > 1
775
+ options[:phrase] = args[1..-1].join(" ")
721
776
  end
722
- image_name = args[0]
723
777
  connect(options)
724
- begin
725
- image = find_virtual_image_by_name_or_id(image_name)
726
- return 1 if image.nil?
727
- unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image #{image['name']}?")
728
- exit
729
- end
730
- @virtual_images_interface.setopts(options)
731
- if options[:dry_run]
732
- print_dry_run @virtual_images_interface.dry.destroy(image['id'])
733
- return
734
- end
735
- json_response = @virtual_images_interface.destroy(image['id'])
736
- if options[:json]
737
- print JSON.pretty_generate(json_response)
778
+ image = find_virtual_image_by_name_or_id(args[0])
779
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
780
+ params.merge!(parse_list_options(options))
781
+ @virtual_images_interface.setopts(options)
782
+ if options[:dry_run]
783
+ print_dry_run @virtual_images_interface.dry.list_locations(image['id'], params)
784
+ return
785
+ end
786
+ json_response = @virtual_images_interface.list_locations(image['id'], params)
787
+ records = json_response['locations']
788
+ render_response(json_response, options, 'virtualImages') do
789
+ title = "Virtual Image Locations"
790
+ subtitles = parse_list_subtitles(options)
791
+ print_h1 title, subtitles
792
+ if records.empty?
793
+ print cyan,"No virtual image locations found.",reset,"\n"
738
794
  else
739
- print "\n", cyan, "Virtual Image #{image['name']} removed", reset, "\n\n"
795
+ print as_pretty_table(records, virtual_image_location_list_column_definitions.upcase_keys!, options)
796
+ print_results_pagination(json_response)
740
797
  end
741
- rescue RestClient::Exception => e
742
- print_rest_exception(e, options)
743
- exit 1
798
+ print reset,"\n"
799
+ end
800
+ return 0, nil
801
+ end
802
+
803
+ def get_location(args)
804
+ params = {}
805
+ options = {}
806
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
807
+ opts.banner = subcommand_usage("[image] [location]")
808
+ build_standard_remove_options(opts, options)
809
+ opts.footer = <<-EOT
810
+ Get details about a virtual image location.
811
+ [image] is required. This is the name or id of a virtual image.
812
+ [location] is required. This is the name or id of a virtual image location.
813
+ EOT
744
814
  end
815
+ optparse.parse!(args)
816
+ verify_args!(args:args, optparse:optparse, count:2)
817
+ connect(options)
818
+ image = find_virtual_image_by_name_or_id(args[0])
819
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
820
+ location = find_virtual_image_location_by_name_or_id(image['id'], args[1])
821
+ return 1, "location not found for '#{args[1]}'" if location.nil?
822
+ params.merge!(parse_query_options(options))
823
+ @virtual_images_interface.setopts(options)
824
+ if options[:dry_run]
825
+ print_dry_run @virtual_images_interface.dry.get_location(image['id'], location['id'])
826
+ return 0, nil
827
+ end
828
+ # json_response = @virtual_images_interface.get(image['id'], location['id'])
829
+ json_response = {'location' => location} # skip redundant request
830
+ render_response(json_response, options, 'location') do
831
+ location = json_response['location']
832
+ volumes = location['volumes'] || []
833
+ print_h1 "Virtual Image Location Details", [], options
834
+ print_description_list(virtual_image_location_column_definitions, location, options)
835
+ if volumes && !volumes.empty?
836
+ print_h2 "Volumes", options
837
+ volume_rows = location_volumes.collect do |volume|
838
+ {name: volume['name'], size: Filesize.from("#{volume['rawSize']} B").pretty}
839
+ end
840
+ print cyan
841
+ print as_pretty_table(volume_rows, [:name, :size], options)
842
+ print cyan
843
+ # print "\n", reset
844
+ end
845
+ print reset,"\n"
846
+ end
847
+ return 0, nil
745
848
  end
746
849
 
850
+ def remove_location(args)
851
+ params = {}
852
+ options = {}
853
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
854
+ opts.banner = subcommand_usage("[image] [location]")
855
+ opts.on('--remove-from-cloud [true|false]', String, "Remove from cloud. Default is true.") do |val|
856
+ options[:options]['removeFromCloud'] = ['','true','on'].include?(val.to_s)
857
+ end
858
+ build_standard_remove_options(opts, options)
859
+ opts.footer = <<-EOT
860
+ Delete a virtual image location.
861
+ [image] is required. This is the name or id of a virtual image.
862
+ [location] is required. This is the name or id of a virtual image location.
863
+ EOT
864
+ end
865
+ optparse.parse!(args)
866
+ verify_args!(args:args, optparse:optparse, count:2)
867
+ connect(options)
868
+ image = find_virtual_image_by_name_or_id(args[0])
869
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
870
+ location = find_virtual_image_location_by_name_or_id(image['id'], args[1])
871
+ return 1, "location not found for '#{args[1]}'" if location.nil?
872
+
873
+ params.merge!(parse_query_options(options))
874
+
875
+ # Delete prompt
876
+ # [ X ] Remove from cloud
877
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'removeFromCloud', 'fieldLabel' => 'Remove from cloud', 'type' => 'checkbox', 'defaultValue' => true, 'required' => true, 'description' => "Remove from cloud"}], options[:options], @api_client)
878
+ remove_from_cloud = v_prompt['removeFromCloud'].to_s == 'true' || v_prompt['removeFromCloud'].to_s == 'on'
879
+ params['removeFromCloud'] = remove_from_cloud
880
+
881
+ # Delete confirmation
882
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image location #{location['id']}?")
883
+ return 9, "aborted"
884
+ end
885
+
886
+ @virtual_images_interface.setopts(options)
887
+ if options[:dry_run]
888
+ print_dry_run @virtual_images_interface.dry.destroy_location(image['id'], location['id'], params)
889
+ return
890
+ end
891
+ json_response = @virtual_images_interface.destroy_location(image['id'], location['id'], params)
892
+ render_response(json_response, options) do
893
+ print_green_success "Removed virtual image location #{location['id']}"
894
+ end
895
+ return 0, nil
896
+ end
747
897
 
748
898
  private
749
- def find_virtual_image_by_name_or_id(val)
899
+
900
+ def find_virtual_image_by_name_or_id(val)
750
901
  if val.to_s =~ /\A\d{1,}\Z/
751
902
  return find_virtual_image_by_id(val)
752
903
  else
@@ -911,4 +1062,75 @@ EOT
911
1062
  out
912
1063
  end
913
1064
 
1065
+
1066
+ ## Virtual Image Locations
1067
+
1068
+ def virtual_image_location_object_key
1069
+ "location"
1070
+ end
1071
+
1072
+ def virtual_image_location_list_key
1073
+ "locations"
1074
+ end
1075
+
1076
+ def find_virtual_image_location_by_name_or_id(virtual_image_id, val)
1077
+ if val.to_s =~ /\A\d{1,}\Z/
1078
+ return find_virtual_image_location_by_id(virtual_image_id, val)
1079
+ else
1080
+ return find_virtual_image_location_by_name(virtual_image_id, val)
1081
+ end
1082
+ end
1083
+
1084
+ def virtual_image_location_list_column_definitions
1085
+ virtual_image_location_column_definitions
1086
+ end
1087
+
1088
+ def virtual_image_location_column_definitions
1089
+ {
1090
+ "ID" => 'id',
1091
+ "Name" => 'imageName',
1092
+ "Cloud" => lambda {|it| it['cloud']['name'] rescue '' },
1093
+ "Public" => lambda {|it| format_boolean(it['isPublic']) },
1094
+ "Region" => lambda {|it| it['imageRegion'] },
1095
+ "External ID" => lambda {|it| it['externalId'] },
1096
+ "Price Plan" => lambda {|it| it['pricePlan'] ? it['pricePlan']['name'] : nil },
1097
+ # "Virtual Image" => lambda {|it| it['virtualImage']['name'] rescue '' },
1098
+ # "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
1099
+ # "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
1100
+ }
1101
+ end
1102
+
1103
+
1104
+ def find_virtual_image_location_by_id(virtual_image_id, id)
1105
+ begin
1106
+ json_response = @virtual_images_interface.get_location(virtual_image_id, id.to_i)
1107
+ return json_response[virtual_image_location_object_key]
1108
+ rescue RestClient::Exception => e
1109
+ if e.response && e.response.code == 404
1110
+ print_red_alert "Virtual Image Location not found by id '#{id}'"
1111
+ else
1112
+ raise e
1113
+ end
1114
+ end
1115
+ end
1116
+
1117
+ def find_virtual_image_location_by_name(virtual_image_id, name)
1118
+ json_response = @virtual_images_interface.list_locations(virtual_image_id, {imageName: name.to_s})
1119
+ virtual_image_locations = json_response[virtual_image_location_list_key]
1120
+ if virtual_image_locations.empty?
1121
+ print_red_alert "Virtual Image Location not found by name '#{name}'"
1122
+ return nil
1123
+ elsif virtual_image_locations.size > 1
1124
+ print_red_alert "#{virtual_image_locations.size} Virtual Image Locations found by name '#{name}'"
1125
+ print_error "\n"
1126
+ puts_error as_pretty_table(virtual_image_locations, {"ID" => 'id', "NAME" => 'imageName'}, {color:red})
1127
+ print_red_alert "Try using ID instead"
1128
+ print_error reset,"\n"
1129
+ return nil
1130
+ else
1131
+ return virtual_image_locations[0]
1132
+ end
1133
+ end
1134
+
1135
+
914
1136
  end
data/lib/morpheus/cli.rb CHANGED
@@ -50,7 +50,7 @@ module Morpheus
50
50
  Dir[File.dirname(__FILE__) + "/api/**/*.rb"].each {|file| load file }
51
51
 
52
52
  # load mixins
53
- Dir[File.dirname(__FILE__) + "/cli/mixins/*.rb"].each {|file| load file }
53
+ Dir[File.dirname(__FILE__) + "/cli/mixins/**/*.rb"].each {|file| load file }
54
54
 
55
55
  # load commands
56
56
  # Dir[File.dirname(__FILE__) + "/cli/*.rb"].each {|file| load file }
@@ -93,6 +93,13 @@ module Morpheus
93
93
  load 'morpheus/cli/cloud_folders_command.rb'
94
94
  load 'morpheus/cli/hosts.rb'
95
95
  load 'morpheus/cli/load_balancers.rb'
96
+ load 'morpheus/cli/load_balancer_virtual_servers.rb'
97
+ # load 'morpheus/cli/load_balancer_monitors.rb'
98
+ # load 'morpheus/cli/load_balancer_nodes.rb'
99
+ # load 'morpheus/cli/load_balancer_policies.rb'
100
+ load 'morpheus/cli/load_balancer_pools.rb'
101
+ # load 'morpheus/cli/load_balancer_profiles.rb'
102
+ # load 'morpheus/cli/load_balancer_scripts.rb'
96
103
  load 'morpheus/cli/load_balancer_types.rb'
97
104
  load 'morpheus/cli/shell.rb'
98
105
  load 'morpheus/cli/tasks.rb'
@@ -186,6 +193,7 @@ module Morpheus
186
193
  load 'morpheus/cli/vdi_gateways_command.rb'
187
194
  load 'morpheus/cli/vdi_command.rb' # (VDI persona)
188
195
  load 'morpheus/cli/certificates_command.rb' # (VDI persona)
196
+ #load 'morpheus/cli/network_scopes_command.rb'
189
197
  # add new commands here...
190
198
 
191
199
  end
data/morpheus-cli.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.required_ruby_version = '>= 2.5.1' # according to http.rb doc
22
- spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "bundler", "~> 2.2"
23
23
  spec.add_development_dependency "rake"
24
24
  spec.add_dependency 'term-ansicolor', '~> 1.3.0'
25
25
  spec.add_dependency "rest-client", "2.0.2"
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.3.2.1
4
+ version: 5.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Estes
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2021-08-11 00:00:00.000000000 Z
14
+ date: 2021-11-09 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -19,14 +19,14 @@ dependencies:
19
19
  requirements:
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: '1.6'
22
+ version: '2.2'
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '1.6'
29
+ version: '2.2'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -237,6 +237,7 @@ files:
237
237
  - lib/morpheus/api/library_spec_templates_interface.rb
238
238
  - lib/morpheus/api/license_interface.rb
239
239
  - lib/morpheus/api/load_balancer_pools_interface.rb
240
+ - lib/morpheus/api/load_balancer_profiles_interface.rb
240
241
  - lib/morpheus/api/load_balancer_types_interface.rb
241
242
  - lib/morpheus/api/load_balancer_virtual_servers_interface.rb
242
243
  - lib/morpheus/api/load_balancers_interface.rb
@@ -258,6 +259,7 @@ files:
258
259
  - lib/morpheus/api/network_proxies_interface.rb
259
260
  - lib/morpheus/api/network_routers_interface.rb
260
261
  - lib/morpheus/api/network_security_servers_interface.rb
262
+ - lib/morpheus/api/network_servers_interface.rb
261
263
  - lib/morpheus/api/network_services_interface.rb
262
264
  - lib/morpheus/api/network_subnets_interface.rb
263
265
  - lib/morpheus/api/network_types_interface.rb
@@ -307,6 +309,7 @@ files:
307
309
  - lib/morpheus/api/vdi_interface.rb
308
310
  - lib/morpheus/api/vdi_pools_interface.rb
309
311
  - lib/morpheus/api/virtual_images_interface.rb
312
+ - lib/morpheus/api/virtual_servers_interface.rb
310
313
  - lib/morpheus/api/whitelabel_settings_interface.rb
311
314
  - lib/morpheus/api/whoami_interface.rb
312
315
  - lib/morpheus/api/wiki_interface.rb
@@ -397,7 +400,9 @@ files:
397
400
  - lib/morpheus/cli/library_spec_templates_command.rb
398
401
  - lib/morpheus/cli/library_upgrades_command.rb
399
402
  - lib/morpheus/cli/license.rb
403
+ - lib/morpheus/cli/load_balancer_pools.rb
400
404
  - lib/morpheus/cli/load_balancer_types.rb
405
+ - lib/morpheus/cli/load_balancer_virtual_servers.rb
401
406
  - lib/morpheus/cli/load_balancers.rb
402
407
  - lib/morpheus/cli/log_settings_command.rb
403
408
  - lib/morpheus/cli/login.rb
@@ -418,6 +423,7 @@ files:
418
423
  - lib/morpheus/cli/mixins/provisioning_helper.rb
419
424
  - lib/morpheus/cli/mixins/remote_helper.rb
420
425
  - lib/morpheus/cli/mixins/rest_command.rb
426
+ - lib/morpheus/cli/mixins/secondary_rest_command.rb
421
427
  - lib/morpheus/cli/mixins/vdi_helper.rb
422
428
  - lib/morpheus/cli/mixins/whoami_helper.rb
423
429
  - lib/morpheus/cli/monitoring_alerts_command.rb
@@ -432,6 +438,7 @@ files:
432
438
  - lib/morpheus/cli/network_pools_command.rb
433
439
  - lib/morpheus/cli/network_proxies_command.rb
434
440
  - lib/morpheus/cli/network_routers_command.rb
441
+ - lib/morpheus/cli/network_scopes_command.rb
435
442
  - lib/morpheus/cli/network_services_command.rb
436
443
  - lib/morpheus/cli/networks_command.rb
437
444
  - lib/morpheus/cli/option_parser.rb