morpheus-cli 5.3.2.3 → 5.3.3

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.
@@ -158,11 +158,13 @@ class Morpheus::Cli::MonitoringChecksCommand
158
158
  end
159
159
  },
160
160
  "Type" => lambda {|it| format_monitoring_check_type(it) },
161
+ "API Key" => lambda {|it| it['apiKey'] },
161
162
  "Created By" => lambda {|it| it['createdBy'] ? it['createdBy']['username'] : "System" },
162
163
  "Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
163
164
  "Last Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
164
165
  # "Last Error" => lambda {|it| format_local_dt(it['lastErrorDate']) },
165
166
  }
167
+ description_cols.delete("API Key") if !['pushCheck'].include?(check['checkType']['code']) || check['apiKey'].nil?
166
168
  print_description_list(description_cols, check)
167
169
 
168
170
  # Last Error
@@ -619,7 +619,7 @@ class Morpheus::Cli::NetworksCommand
619
619
  api_params['network.site.id'] = group ? group['id'] : 'shared'
620
620
  api_params['network.type.id'] = network_type['id']
621
621
  api_params['network.networkServer.id'] = network_server_id if !network_server_id.nil?
622
- network_type_params = Morpheus::Cli::OptionTypes.prompt(network_type_option_types,options[:options],@api_client, api_params)
622
+ network_type_params = Morpheus::Cli::OptionTypes.prompt(network_type_option_types,(options[:options] || {}).merge(payload),@api_client, api_params)
623
623
  # network context options belong at network level and not network.network
624
624
  network_context_params = network_type_params.delete('network')
625
625
  payload['network'].deep_merge!(network_context_params) if network_context_params
@@ -32,27 +32,35 @@ module Morpheus
32
32
  #out << "Options:\n"
33
33
  # the default way..
34
34
  # out << summarize().join("")
35
-
36
35
  # super hacky, should be examining the option, not the fully formatted description
37
36
  my_summaries = summarize()
38
- summarize().each do |opt_description|
39
- is_hidden = (@hidden_options || []).find { |hidden_switch|
40
- # opt_description.include?("--#{hidden_switch}")
41
- if hidden_switch.start_with?("-")
42
- opt_description.to_s.strip.start_with?("#{hidden_switch} ")
43
- else
44
- opt_description.to_s.strip.start_with?("--#{hidden_switch} ")
45
- end
46
- }
47
- if is_hidden
48
- if opts[:show_hidden_options]
49
- # out << opt_description + " (hidden)"
50
- out << opt_description
37
+ if opts[:show_hidden_options]
38
+ my_summaries.each do |full_line|
39
+ out << full_line
40
+ end
41
+ else
42
+ on_hidden_option = false
43
+ my_summaries.each do |full_line|
44
+ opt_description = full_line.to_s.strip
45
+ if opt_description.start_with?("-")
46
+ is_hidden = (@hidden_options || []).find { |hidden_switch|
47
+ if hidden_switch.start_with?("-")
48
+ opt_description.start_with?("#{hidden_switch} ")
49
+ else
50
+ opt_description.start_with?("--#{hidden_switch} ")
51
+ end
52
+ }
53
+ if is_hidden
54
+ on_hidden_option = true
55
+ else
56
+ on_hidden_option = false
57
+ out << full_line
58
+ end
51
59
  else
52
- # hidden
60
+ if on_hidden_option == false
61
+ out << full_line
62
+ end
53
63
  end
54
- else
55
- out << opt_description
56
64
  end
57
65
  end
58
66
  end
@@ -61,11 +61,11 @@ module Morpheus
61
61
  ).each do |option_type|
62
62
  context_map = results
63
63
  value = nil
64
- value_found=false
64
+ value_found = false
65
+ field_group = (option_type['fieldGroup'] || 'default').to_s.sub(/options\Z/i, "").strip # avoid "ADVANCED OPTION OPTIONS"
65
66
 
66
- if cur_field_group != (option_type['fieldGroup'] || 'default')
67
- cur_field_group = option_type['fieldGroup']
68
- cur_field_group = cur_field_group.to_s.sub(/options\Z/i, "").strip # avoid "ADVANCED OPTION OPTIONS"
67
+ if cur_field_group != field_group
68
+ cur_field_group = field_group
69
69
  print "\n#{cur_field_group.upcase} OPTIONS\n#{"=" * ("#{cur_field_group} OPTIONS".length)}\n\n"
70
70
  end
71
71
 
@@ -102,10 +102,10 @@ module Morpheus
102
102
  end
103
103
 
104
104
  found_dep_value = match_type == 'all' ? true : false
105
- visible_option_check_value.split(',').each do |value|
105
+ visible_option_check_value.sub(',', ' ').split(' ').each do |value|
106
106
  parts = value.split(':')
107
107
  depends_on_code = parts[0]
108
- depends_on_value = parts.count > 1 ? parts[1].to_s.strip : '.'
108
+ depends_on_value = parts.count > 1 ? parts[1].to_s.strip : nil
109
109
  depends_on_option_type = option_types.find {|it| it["code"] == depends_on_code }
110
110
  if !depends_on_option_type
111
111
  depends_on_option_type = option_types.find {|it|
@@ -115,13 +115,18 @@ module Morpheus
115
115
 
116
116
  if depends_on_option_type
117
117
  depends_on_field_key = depends_on_option_type['fieldContext'].nil? || depends_on_option_type['fieldContext'].empty? ? "#{depends_on_option_type['fieldName']}" : "#{depends_on_option_type['fieldContext']}.#{depends_on_option_type['fieldName']}"
118
- field_value = get_object_value(results, depends_on_field_key) || get_object_value(options, depends_on_field_key)
118
+ else
119
+ depends_on_field_key = depends_on_code
120
+ end
119
121
 
120
- if !field_value.nil? && field_value.match?(depends_on_value)
121
- found_dep_value = true if match_type != 'all'
122
- else
123
- found_dep_value = false if match_type == 'all'
124
- end
122
+ field_value = get_object_value(results, depends_on_field_key) ||
123
+ get_object_value(options, depends_on_field_key) ||
124
+ get_object_value(api_params, depends_on_field_key)
125
+
126
+ if !field_value.nil? && (depends_on_value.nil? || depends_on_value.empty? || field_value.match?(depends_on_value))
127
+ found_dep_value = true if match_type != 'all'
128
+ else
129
+ found_dep_value = false if match_type == 'all'
125
130
  end
126
131
  end
127
132
  next if !found_dep_value
@@ -237,7 +242,7 @@ module Morpheus
237
242
  # I suppose the entered value should take precedence
238
243
  # api_params = api_params.merge(options) # this might be good enough
239
244
  # dup it
240
- value = select_prompt(option_type, api_client, (option_type['noParams'] ? {} : (api_params || {}).merge(results)), options[:no_prompt], nil, paging_enabled)
245
+ value = select_prompt(option_type, api_client, (option_type['noParams'] ? {} : (api_params || {}).deep_merge(results)), options[:no_prompt], nil, paging_enabled)
241
246
  if value && option_type['type'] == 'multiSelect'
242
247
  value = [value]
243
248
  while self.confirm("Add another #{option_type['fieldLabel']}?", {:default => false}) do
@@ -276,7 +281,8 @@ module Morpheus
276
281
  value = [value] if !value.nil? && !value.is_a?(Array)
277
282
  # parent_context_map[parent_ns] = value
278
283
  end
279
- context_map[field_name] = value
284
+ context_map[field_name] = value if !(value.nil? || (value.is_a?(Hash) && value.empty?))
285
+ parent_context_map.reject! {|k,v| k == parent_ns && (v.nil? || (v.is_a?(Hash) && v.empty?))}
280
286
  end
281
287
  results
282
288
  end
@@ -947,8 +953,9 @@ module Morpheus
947
953
  out << "\n"
948
954
  out << "#{header}\n"
949
955
  out << "#{'=' * header.length}\n"
956
+
950
957
  select_options.each do |option|
951
- out << " * #{option['name']} [#{option['value']}]\n"
958
+ out << (option['isGroup'] ? "- #{option['name']}\n" : " * #{option['name']} [#{option['value']}]\n")
952
959
  end
953
960
  return out
954
961
  end
@@ -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.3"
4
+ VERSION = "5.3.3"
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
@@ -188,6 +187,7 @@ EOT
188
187
  image = json_response['virtualImage']
189
188
  image_config = image['config'] || {}
190
189
  image_volumes = image['volumes'] || []
190
+ image_locations = image['locations'] || []
191
191
  image_files = json_response['cloudFiles'] || json_response['files']
192
192
  image_type = virtual_image_type_for_name_or_code(image['imageType'])
193
193
  image_type_display = image_type ? "#{image_type['name']}" : image['imageType']
@@ -255,7 +255,7 @@ EOT
255
255
  # print "\n", reset
256
256
  end
257
257
 
258
- if image_files
258
+ if image_files && !image_files.empty?
259
259
  print_h2 "Files (#{image_files.size})"
260
260
  # image_files.each {|image_file|
261
261
  # pretty_filesize = Filesize.from("#{image_file['size']} B").pretty
@@ -270,6 +270,11 @@ EOT
270
270
  print as_pretty_table(image_file_rows, [:filename, :size])
271
271
  # print reset,"\n"
272
272
  end
273
+
274
+ if image_locations && !image_locations.empty?
275
+ print_h2 "Locations", options
276
+ print as_pretty_table(image_locations, virtual_image_location_list_column_definitions.upcase_keys!, options)
277
+ end
273
278
 
274
279
  if options[:details] && image_config && !image_config.empty?
275
280
  print_h2 "Config", options
@@ -689,7 +694,7 @@ EOT
689
694
  image = find_virtual_image_by_name_or_id(image_name)
690
695
  return 1 if image.nil?
691
696
  unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image filename #{filename}?")
692
- exit
697
+ return 9, "aborted"
693
698
  end
694
699
  @virtual_images_interface.setopts(options)
695
700
  if options[:dry_run]
@@ -709,44 +714,188 @@ EOT
709
714
  end
710
715
 
711
716
  def remove(args)
717
+ params = {}
712
718
  options = {}
713
719
  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])
720
+ opts.banner = subcommand_usage("[image] [location]")
721
+ opts.on('--remove-from-cloud [true|false]', String, "Remove from all clouds. Default is true.") do |val|
722
+ options[:options]['removeFromCloud'] = ['','true','on'].include?(val.to_s)
723
+ end
724
+ build_standard_remove_options(opts, options)
725
+ opts.footer = <<-EOT
726
+ Delete a virtual image.
727
+ [image] is required. This is the name or id of a virtual image.
728
+ EOT
716
729
  end
717
730
  optparse.parse!(args)
718
- if args.count < 1
719
- puts optparse
720
- exit 1
731
+ verify_args!(args:args, optparse:optparse, count:1)
732
+ connect(options)
733
+ image = find_virtual_image_by_name_or_id(args[0])
734
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
735
+ params.merge!(parse_query_options(options))
736
+ # Delete prompt
737
+ # [ X ] Remove from all clouds
738
+ 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)
739
+ remove_from_cloud = v_prompt['removeFromCloud'].to_s == 'true' || v_prompt['removeFromCloud'].to_s == 'on'
740
+ params['removeFromCloud'] = remove_from_cloud
741
+
742
+ # Delete confirmation
743
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image #{image['name']}?")
744
+ return 9, "aborted"
745
+ end
746
+
747
+ @virtual_images_interface.setopts(options)
748
+ if options[:dry_run]
749
+ print_dry_run @virtual_images_interface.dry.destroy(image['id'], params)
750
+ return
751
+ end
752
+ json_response = @virtual_images_interface.destroy(image['id'], params)
753
+ render_response(json_response, options) do
754
+ print_green_success "Removed virtual image #{image['name']}"
755
+ end
756
+ return 0, nil
757
+ end
758
+
759
+ def list_locations(args)
760
+ params = {}
761
+ options = {}
762
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
763
+ opts.banner = subcommand_usage("[image]")
764
+ build_standard_list_options(opts, options)
765
+ opts.footer = <<-EOT
766
+ List virtual image locations for a specific virtual image.
767
+ [image] is required. This is the name or id of a virtual image.
768
+ EOT
769
+ end
770
+ optparse.parse!(args)
771
+ verify_args!(args:args, optparse:optparse, min:1)
772
+ if args.count > 1
773
+ options[:phrase] = args[1..-1].join(" ")
721
774
  end
722
- image_name = args[0]
723
775
  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)
776
+ image = find_virtual_image_by_name_or_id(args[0])
777
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
778
+ params.merge!(parse_list_options(options))
779
+ @virtual_images_interface.setopts(options)
780
+ if options[:dry_run]
781
+ print_dry_run @virtual_images_interface.dry.list_locations(image['id'], params)
782
+ return
783
+ end
784
+ json_response = @virtual_images_interface.list_locations(image['id'], params)
785
+ records = json_response['locations']
786
+ render_response(json_response, options, 'virtualImages') do
787
+ title = "Virtual Image Locations"
788
+ subtitles = parse_list_subtitles(options)
789
+ print_h1 title, subtitles
790
+ if records.empty?
791
+ print cyan,"No virtual image locations found.",reset,"\n"
738
792
  else
739
- print "\n", cyan, "Virtual Image #{image['name']} removed", reset, "\n\n"
793
+ print as_pretty_table(records, virtual_image_location_list_column_definitions.upcase_keys!, options)
794
+ print_results_pagination(json_response)
740
795
  end
741
- rescue RestClient::Exception => e
742
- print_rest_exception(e, options)
743
- exit 1
796
+ print reset,"\n"
797
+ end
798
+ return 0, nil
799
+ end
800
+
801
+ def get_location(args)
802
+ params = {}
803
+ options = {}
804
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
805
+ opts.banner = subcommand_usage("[image] [location]")
806
+ build_standard_remove_options(opts, options)
807
+ opts.footer = <<-EOT
808
+ Get details about a virtual image location.
809
+ [image] is required. This is the name or id of a virtual image.
810
+ [location] is required. This is the name or id of a virtual image location.
811
+ EOT
744
812
  end
813
+ optparse.parse!(args)
814
+ verify_args!(args:args, optparse:optparse, count:2)
815
+ connect(options)
816
+ image = find_virtual_image_by_name_or_id(args[0])
817
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
818
+ location = find_virtual_image_location_by_name_or_id(image['id'], args[1])
819
+ return 1, "location not found for '#{args[1]}'" if location.nil?
820
+ params.merge!(parse_query_options(options))
821
+ @virtual_images_interface.setopts(options)
822
+ if options[:dry_run]
823
+ print_dry_run @virtual_images_interface.dry.get_location(image['id'], location['id'])
824
+ return 0, nil
825
+ end
826
+ # json_response = @virtual_images_interface.get(image['id'], location['id'])
827
+ json_response = {'location' => location} # skip redundant request
828
+ render_response(json_response, options, 'location') do
829
+ location = json_response['location']
830
+ volumes = location['volumes'] || []
831
+ print_h1 "Virtual Image Location Details", [], options
832
+ print_description_list(virtual_image_location_column_definitions, location, options)
833
+ if volumes && !volumes.empty?
834
+ print_h2 "Volumes", options
835
+ volume_rows = location_volumes.collect do |volume|
836
+ {name: volume['name'], size: Filesize.from("#{volume['rawSize']} B").pretty}
837
+ end
838
+ print cyan
839
+ print as_pretty_table(volume_rows, [:name, :size], options)
840
+ print cyan
841
+ # print "\n", reset
842
+ end
843
+ print reset,"\n"
844
+ end
845
+ return 0, nil
745
846
  end
746
847
 
848
+ def remove_location(args)
849
+ params = {}
850
+ options = {}
851
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
852
+ opts.banner = subcommand_usage("[image] [location]")
853
+ opts.on('--remove-from-cloud [true|false]', String, "Remove from cloud. Default is true.") do |val|
854
+ options[:options]['removeFromCloud'] = ['','true','on'].include?(val.to_s)
855
+ end
856
+ build_standard_remove_options(opts, options)
857
+ opts.footer = <<-EOT
858
+ Delete a virtual image location.
859
+ [image] is required. This is the name or id of a virtual image.
860
+ [location] is required. This is the name or id of a virtual image location.
861
+ EOT
862
+ end
863
+ optparse.parse!(args)
864
+ verify_args!(args:args, optparse:optparse, count:2)
865
+ connect(options)
866
+ image = find_virtual_image_by_name_or_id(args[0])
867
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
868
+ location = find_virtual_image_location_by_name_or_id(image['id'], args[1])
869
+ return 1, "location not found for '#{args[1]}'" if location.nil?
870
+
871
+ params.merge!(parse_query_options(options))
872
+
873
+ # Delete prompt
874
+ # [ X ] Remove from cloud
875
+ 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)
876
+ remove_from_cloud = v_prompt['removeFromCloud'].to_s == 'true' || v_prompt['removeFromCloud'].to_s == 'on'
877
+ params['removeFromCloud'] = remove_from_cloud
878
+
879
+ # Delete confirmation
880
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image location #{location['id']}?")
881
+ return 9, "aborted"
882
+ end
883
+
884
+ @virtual_images_interface.setopts(options)
885
+ if options[:dry_run]
886
+ print_dry_run @virtual_images_interface.dry.destroy_location(image['id'], location['id'], params)
887
+ return
888
+ end
889
+ json_response = @virtual_images_interface.destroy_location(image['id'], location['id'], params)
890
+ render_response(json_response, options) do
891
+ print_green_success "Removed virtual image location #{location['id']}"
892
+ end
893
+ return 0, nil
894
+ end
747
895
 
748
896
  private
749
- def find_virtual_image_by_name_or_id(val)
897
+
898
+ def find_virtual_image_by_name_or_id(val)
750
899
  if val.to_s =~ /\A\d{1,}\Z/
751
900
  return find_virtual_image_by_id(val)
752
901
  else
@@ -911,4 +1060,75 @@ EOT
911
1060
  out
912
1061
  end
913
1062
 
1063
+
1064
+ ## Virtual Image Locations
1065
+
1066
+ def virtual_image_location_object_key
1067
+ "location"
1068
+ end
1069
+
1070
+ def virtual_image_location_list_key
1071
+ "locations"
1072
+ end
1073
+
1074
+ def find_virtual_image_location_by_name_or_id(virtual_image_id, val)
1075
+ if val.to_s =~ /\A\d{1,}\Z/
1076
+ return find_virtual_image_location_by_id(virtual_image_id, val)
1077
+ else
1078
+ return find_virtual_image_location_by_name(virtual_image_id, val)
1079
+ end
1080
+ end
1081
+
1082
+ def virtual_image_location_list_column_definitions
1083
+ virtual_image_location_column_definitions
1084
+ end
1085
+
1086
+ def virtual_image_location_column_definitions
1087
+ {
1088
+ "ID" => 'id',
1089
+ "Name" => 'imageName',
1090
+ "Cloud" => lambda {|it| it['cloud']['name'] rescue '' },
1091
+ "Public" => lambda {|it| format_boolean(it['isPublic']) },
1092
+ "Region" => lambda {|it| it['imageRegion'] },
1093
+ "External ID" => lambda {|it| it['externalId'] },
1094
+ "Price Plan" => lambda {|it| it['pricePlan'] ? it['pricePlan']['name'] : nil },
1095
+ # "Virtual Image" => lambda {|it| it['virtualImage']['name'] rescue '' },
1096
+ # "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
1097
+ # "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
1098
+ }
1099
+ end
1100
+
1101
+
1102
+ def find_virtual_image_location_by_id(virtual_image_id, id)
1103
+ begin
1104
+ json_response = @virtual_images_interface.get_location(virtual_image_id, id.to_i)
1105
+ return json_response[virtual_image_location_object_key]
1106
+ rescue RestClient::Exception => e
1107
+ if e.response && e.response.code == 404
1108
+ print_red_alert "Virtual Image Location not found by id '#{id}'"
1109
+ else
1110
+ raise e
1111
+ end
1112
+ end
1113
+ end
1114
+
1115
+ def find_virtual_image_location_by_name(virtual_image_id, name)
1116
+ json_response = @virtual_images_interface.list_locations(virtual_image_id, {imageName: name.to_s})
1117
+ virtual_image_locations = json_response[virtual_image_location_list_key]
1118
+ if virtual_image_locations.empty?
1119
+ print_red_alert "Virtual Image Location not found by name '#{name}'"
1120
+ return nil
1121
+ elsif virtual_image_locations.size > 1
1122
+ print_red_alert "#{virtual_image_locations.size} Virtual Image Locations found by name '#{name}'"
1123
+ print_error "\n"
1124
+ puts_error as_pretty_table(virtual_image_locations, {"ID" => 'id', "NAME" => 'imageName'}, {color:red})
1125
+ print_red_alert "Try using ID instead"
1126
+ print_error reset,"\n"
1127
+ return nil
1128
+ else
1129
+ return virtual_image_locations[0]
1130
+ end
1131
+ end
1132
+
1133
+
914
1134
  end