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.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +12 -0
- data/lib/morpheus/api/clouds_interface.rb +4 -11
- data/lib/morpheus/api/instances_interface.rb +18 -5
- data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
- data/lib/morpheus/api/load_balancer_profiles_interface.rb +10 -0
- data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +4 -4
- data/lib/morpheus/api/network_routers_interface.rb +21 -0
- data/lib/morpheus/api/network_servers_interface.rb +42 -0
- data/lib/morpheus/api/rest_interface.rb +2 -1
- data/lib/morpheus/api/virtual_images_interface.rb +23 -2
- data/lib/morpheus/api/virtual_servers_interface.rb +9 -0
- data/lib/morpheus/cli/apps.rb +3 -2
- data/lib/morpheus/cli/cli_command.rb +14 -6
- data/lib/morpheus/cli/cli_registry.rb +55 -2
- data/lib/morpheus/cli/cloud_resource_pools_command.rb +170 -134
- data/lib/morpheus/cli/clouds.rb +22 -40
- data/lib/morpheus/cli/clusters.rb +51 -33
- data/lib/morpheus/cli/hosts.rb +0 -1
- data/lib/morpheus/cli/instances.rb +372 -150
- data/lib/morpheus/cli/invoices_command.rb +117 -133
- data/lib/morpheus/cli/library_cluster_layouts_command.rb +20 -0
- data/lib/morpheus/cli/library_option_lists_command.rb +3 -3
- data/lib/morpheus/cli/load_balancer_pools.rb +111 -0
- data/lib/morpheus/cli/load_balancer_virtual_servers.rb +136 -0
- data/lib/morpheus/cli/load_balancers.rb +0 -155
- data/lib/morpheus/cli/mixins/load_balancers_helper.rb +2 -2
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +155 -112
- data/lib/morpheus/cli/mixins/rest_command.rb +53 -37
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +488 -0
- data/lib/morpheus/cli/monitoring_checks_command.rb +2 -0
- data/lib/morpheus/cli/network_routers_command.rb +291 -7
- data/lib/morpheus/cli/network_scopes_command.rb +442 -0
- data/lib/morpheus/cli/networks_command.rb +3 -3
- data/lib/morpheus/cli/option_parser.rb +25 -17
- data/lib/morpheus/cli/option_types.rb +42 -15
- data/lib/morpheus/cli/subnets_command.rb +7 -2
- data/lib/morpheus/cli/tasks.rb +25 -2
- data/lib/morpheus/cli/vdi_pools_command.rb +4 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +251 -29
- data/lib/morpheus/cli.rb +9 -1
- data/morpheus-cli.gemspec +1 -1
- metadata +11 -4
data/lib/morpheus/cli/tasks.rb
CHANGED
@@ -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|
|
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
|
-
|
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},
|
data/lib/morpheus/cli/version.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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("[
|
715
|
-
|
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
|
-
|
719
|
-
|
720
|
-
|
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
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
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
|
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
|
-
|
742
|
-
|
743
|
-
|
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
|
-
|
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
|
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", "~>
|
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.
|
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-
|
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: '
|
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: '
|
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
|