morpheus-cli 2.11.0 → 2.11.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.
@@ -46,7 +46,7 @@ class Morpheus::Cli::Logout
46
46
  return 1
47
47
  end
48
48
  creds = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url)
49
- token = creds.saved_credentials
49
+ token = creds.load_saved_credentials
50
50
  if !token
51
51
  if !options[:quiet]
52
52
  puts "You are not currently logged in to #{display_appliance(@appliance_name, @appliance_url)}"
@@ -229,6 +229,15 @@ module Morpheus::Cli::ProvisioningHelper
229
229
  }
230
230
  }
231
231
 
232
+ # allow arbitrary -O values passed by the user (config and instance namespace only)
233
+ if options[:options] && options[:options]['config'].is_a?(Hash)
234
+ payload['config'] ||= {}
235
+ payload['config'].deep_merge!(options[:options]['config'])
236
+ end
237
+ if options[:options] && options[:options]['instance'].is_a?(Hash)
238
+ payload['instance'].deep_merge!(options[:options]['instance'])
239
+ end
240
+
232
241
  # Description
233
242
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false}], options[:options])
234
243
  payload['instance']['description'] = v_prompt['description'] if !v_prompt['description'].empty?
@@ -304,6 +313,11 @@ module Morpheus::Cli::ProvisioningHelper
304
313
  payload.deep_merge!(provision_payload)
305
314
  end
306
315
 
316
+ ## Advanced Options
317
+
318
+ # scale factor
319
+
320
+
307
321
  # prompt for environment variables
308
322
  evars = prompt_evars(options)
309
323
  if !evars.empty?
@@ -779,162 +793,162 @@ module Morpheus::Cli::ProvisioningHelper
779
793
  end
780
794
 
781
795
 
782
- # This recreates the behavior of multi_networks.js
783
- # This is used by both `instances add` and `hosts add`
784
- # returns array of networkInterfaces based on provision type and cloud settings
785
- def prompt_network_interfaces(zone_id, provision_type_id, options={})
786
- #puts "Configure Networks:"
787
- no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
788
- network_interfaces = []
789
-
790
- zone_network_options_json = api_client.options.options_for_source('zoneNetworkOptions', {zoneId: zone_id, provisionTypeId: provision_type_id})
791
- # puts "zoneNetworkOptions JSON"
792
- # puts JSON.pretty_generate(zone_network_options_json)
793
- zone_network_data = zone_network_options_json['data'] || {}
794
- networks = zone_network_data['networks']
795
- network_interface_types = (zone_network_data['networkTypes'] || []).sort { |x,y| x['displayOrder'] <=> y['displayOrder'] }
796
- enable_network_type_selection = (zone_network_data['enableNetworkTypeSelection'] == 'on' || zone_network_data['enableNetworkTypeSelection'] == true)
797
- has_networks = zone_network_data["hasNetworks"] == true
798
- max_networks = zone_network_data["maxNetworks"] ? zone_network_data["maxNetworks"].to_i : nil
799
-
800
- # skip unless provision type supports networks
801
- if !has_networks
802
- return nil
803
- end
796
+ # This recreates the behavior of multi_networks.js
797
+ # This is used by both `instances add` and `hosts add`
798
+ # returns array of networkInterfaces based on provision type and cloud settings
799
+ def prompt_network_interfaces(zone_id, provision_type_id, options={})
800
+ #puts "Configure Networks:"
801
+ no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
802
+ network_interfaces = []
804
803
 
805
- # no networks available, shouldn't happen
806
- if networks.empty?
807
- return network_interfaces
808
- end
804
+ zone_network_options_json = api_client.options.options_for_source('zoneNetworkOptions', {zoneId: zone_id, provisionTypeId: provision_type_id})
805
+ # puts "zoneNetworkOptions JSON"
806
+ # puts JSON.pretty_generate(zone_network_options_json)
807
+ zone_network_data = zone_network_options_json['data'] || {}
808
+ networks = zone_network_data['networks']
809
+ network_interface_types = (zone_network_data['networkTypes'] || []).sort { |x,y| x['displayOrder'] <=> y['displayOrder'] }
810
+ enable_network_type_selection = (zone_network_data['enableNetworkTypeSelection'] == 'on' || zone_network_data['enableNetworkTypeSelection'] == true)
811
+ has_networks = zone_network_data["hasNetworks"] == true
812
+ max_networks = zone_network_data["maxNetworks"] ? zone_network_data["maxNetworks"].to_i : nil
809
813
 
810
- network_options = []
811
- networks.each do |opt|
812
- if !opt.nil?
813
- network_options << {'name' => opt['name'], 'value' => opt['id']}
814
- end
815
- end
814
+ # skip unless provision type supports networks
815
+ if !has_networks
816
+ return nil
817
+ end
816
818
 
817
- network_interface_type_options = []
818
- network_interface_types.each do |opt|
819
- if !opt.nil?
820
- network_interface_type_options << {'name' => opt['name'], 'value' => opt['id']}
821
- end
822
- end
819
+ # no networks available, shouldn't happen
820
+ if networks.empty?
821
+ return network_interfaces
822
+ end
823
823
 
824
+ network_options = []
825
+ networks.each do |opt|
826
+ if !opt.nil?
827
+ network_options << {'name' => opt['name'], 'value' => opt['id']}
828
+ end
829
+ end
824
830
 
825
- interface_index = 1
826
- add_another_interface = true
827
- while add_another_interface do
828
- # if !no_prompt
829
- # if interface_index == 1
830
- # puts "Configure Network Interface"
831
- # else
832
- # puts "Configure Network Interface #{interface_index}"
833
- # end
834
- # end
831
+ network_interface_type_options = []
832
+ network_interface_types.each do |opt|
833
+ if !opt.nil?
834
+ network_interface_type_options << {'name' => opt['name'], 'value' => opt['id']}
835
+ end
836
+ end
835
837
 
836
- field_context = interface_index == 1 ? "networkInterface" : "networkInterface#{interface_index}"
837
- network_interface = {}
838
838
 
839
- # choose network
840
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'networkId', 'type' => 'select', 'fieldLabel' => "Network", 'selectOptions' => network_options, 'required' => true, 'skipSingleOption' => false, 'description' => 'Choose a network for this interface.', 'defaultValue' => network_interface['networkId']}], options[:options])
841
- network_interface['network'] = {}
842
- network_interface['network']['id'] = v_prompt[field_context]['networkId'].to_i
843
- selected_network = networks.find {|it| it["id"] == network_interface['network']['id'] }
839
+ interface_index = 1
840
+ add_another_interface = true
841
+ while add_another_interface do
842
+ # if !no_prompt
843
+ # if interface_index == 1
844
+ # puts "Configure Network Interface"
845
+ # else
846
+ # puts "Configure Network Interface #{interface_index}"
847
+ # end
848
+ # end
844
849
 
845
- if !selected_network
846
- print_red_alert "Network not found by id #{network_interface['network']['id']}!"
847
- exit 1
848
- end
850
+ field_context = interface_index == 1 ? "networkInterface" : "networkInterface#{interface_index}"
851
+ network_interface = {}
849
852
 
850
- # choose network interface type
851
- if enable_network_type_selection && !network_interface_type_options.empty?
852
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'networkInterfaceTypeId', 'type' => 'select', 'fieldLabel' => "Network Interface Type", 'selectOptions' => network_interface_type_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a network interface type.', 'defaultValue' => network_interface['networkInterfaceTypeId']}], options[:options])
853
- network_interface['networkInterfaceTypeId'] = v_prompt[field_context]['networkInterfaceTypeId'].to_i
854
- end
853
+ # choose network
854
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'networkId', 'type' => 'select', 'fieldLabel' => "Network", 'selectOptions' => network_options, 'required' => true, 'skipSingleOption' => false, 'description' => 'Choose a network for this interface.', 'defaultValue' => network_interface['networkId']}], options[:options])
855
+ network_interface['network'] = {}
856
+ network_interface['network']['id'] = v_prompt[field_context]['networkId'].to_i
857
+ selected_network = networks.find {|it| it["id"] == network_interface['network']['id'] }
855
858
 
856
- # choose IP unless network has a pool configured
857
- if selected_network['pool']
858
- puts "IP Address: Using pool '#{selected_network['pool']['name']}'" if !no_prompt
859
- elsif selected_network['dhcpServer']
860
- puts "IP Address: Using DHCP" if !no_prompt
861
- else
862
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'ipAddress', 'type' => 'text', 'fieldLabel' => "IP Address", 'required' => true, 'description' => 'Enter an IP for this network interface. x.x.x.x', 'defaultValue' => network_interface['ipAddress']}], options[:options])
863
- network_interface['ipAddress'] = v_prompt[field_context]['ipAddress']
864
- end
865
- network_interfaces << network_interface
866
- interface_index += 1
867
- has_another_interface = options[:options] && options[:options]["networkInterface#{interface_index}"]
868
- add_another_interface = has_another_interface || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another network interface?", {:default => false}))
869
- if max_networks && network_interfaces.size >= max_networks
870
- add_another_interface = false
871
- end
859
+ if !selected_network
860
+ print_red_alert "Network not found by id #{network_interface['network']['id']}!"
861
+ exit 1
862
+ end
872
863
 
873
- end
864
+ # choose network interface type
865
+ if enable_network_type_selection && !network_interface_type_options.empty?
866
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'networkInterfaceTypeId', 'type' => 'select', 'fieldLabel' => "Network Interface Type", 'selectOptions' => network_interface_type_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a network interface type.', 'defaultValue' => network_interface['networkInterfaceTypeId']}], options[:options])
867
+ network_interface['networkInterfaceTypeId'] = v_prompt[field_context]['networkInterfaceTypeId'].to_i
868
+ end
874
869
 
875
- return network_interfaces
870
+ # choose IP unless network has a pool configured
871
+ if selected_network['pool']
872
+ puts "IP Address: Using pool '#{selected_network['pool']['name']}'" if !no_prompt
873
+ elsif selected_network['dhcpServer']
874
+ puts "IP Address: Using DHCP" if !no_prompt
875
+ else
876
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'ipAddress', 'type' => 'text', 'fieldLabel' => "IP Address", 'required' => true, 'description' => 'Enter an IP for this network interface. x.x.x.x', 'defaultValue' => network_interface['ipAddress']}], options[:options])
877
+ network_interface['ipAddress'] = v_prompt[field_context]['ipAddress']
878
+ end
879
+ network_interfaces << network_interface
880
+ interface_index += 1
881
+ has_another_interface = options[:options] && options[:options]["networkInterface#{interface_index}"]
882
+ add_another_interface = has_another_interface || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another network interface?", {:default => false}))
883
+ if max_networks && network_interfaces.size >= max_networks
884
+ add_another_interface = false
885
+ end
876
886
 
877
- end
887
+ end
878
888
 
879
- # Prompts user for environment variables for new instance
880
- # returns array of evar objects {id: null, name: "VAR", value: "somevalue"}
881
- def prompt_evars(options={})
882
- #puts "Configure Environment Variables:"
883
- no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
884
- evars = []
885
- evar_index = 0
886
- has_another_evar = options[:options] && options[:options]["evar#{evar_index}"]
887
- add_another_evar = has_another_evar || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add an environment variable?", {default: false}))
888
- while add_another_evar do
889
- field_context = "evar#{evar_index}"
890
- evar = {}
891
- evar['id'] = nil
892
- evar_label = evar_index == 0 ? "ENV" : "ENV [#{evar_index+1}]"
893
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "#{evar_label} Name", 'required' => true, 'description' => 'Environment Variable Name.', 'defaultValue' => evar['name']}], options[:options])
894
- evar['name'] = v_prompt[field_context]['name']
895
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'value', 'type' => 'text', 'fieldLabel' => "#{evar_label} Value", 'required' => true, 'description' => 'Environment Variable Value', 'defaultValue' => evar['value']}], options[:options])
896
- evar['value'] = v_prompt[field_context]['value']
897
- evars << evar
898
- evar_index += 1
899
- has_another_evar = options[:options] && options[:options]["evar#{evar_index}"]
900
- add_another_evar = has_another_evar || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another environment variable?", {default: false}))
901
- end
889
+ return network_interfaces
902
890
 
903
- return evars
904
- end
891
+ end
905
892
 
906
- # reject old volume option types
907
- # these will eventually get removed from the associated optionTypes
908
- def reject_volume_option_types(option_types)
909
- option_types.reject {|opt|
910
- ['osDiskSize', 'osDiskType',
911
- 'diskSize', 'diskType',
912
- 'datastoreId', 'storagePodId'
913
- ].include?(opt['fieldName'])
914
- }
915
- end
893
+ # Prompts user for environment variables for new instance
894
+ # returns array of evar objects {id: null, name: "VAR", value: "somevalue"}
895
+ def prompt_evars(options={})
896
+ #puts "Configure Environment Variables:"
897
+ no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
898
+ evars = []
899
+ evar_index = 0
900
+ has_another_evar = options[:options] && options[:options]["evar#{evar_index}"]
901
+ add_another_evar = has_another_evar || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add an environment variable?", {default: false}))
902
+ while add_another_evar do
903
+ field_context = "evar#{evar_index}"
904
+ evar = {}
905
+ evar['id'] = nil
906
+ evar_label = evar_index == 0 ? "ENV" : "ENV [#{evar_index+1}]"
907
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "#{evar_label} Name", 'required' => true, 'description' => 'Environment Variable Name.', 'defaultValue' => evar['name']}], options[:options])
908
+ evar['name'] = v_prompt[field_context]['name']
909
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'value', 'type' => 'text', 'fieldLabel' => "#{evar_label} Value", 'required' => true, 'description' => 'Environment Variable Value', 'defaultValue' => evar['value']}], options[:options])
910
+ evar['value'] = v_prompt[field_context]['value']
911
+ evars << evar
912
+ evar_index += 1
913
+ has_another_evar = options[:options] && options[:options]["evar#{evar_index}"]
914
+ add_another_evar = has_another_evar || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another environment variable?", {default: false}))
915
+ end
916
+
917
+ return evars
918
+ end
916
919
 
917
- # reject old networking option types
918
- # these will eventually get removed from the associated optionTypes
919
- def reject_networking_option_types(option_types)
920
- option_types.reject {|opt|
921
- ['networkId', 'networkType', 'ipAddress', 'netmask', 'gateway', 'nameservers',
922
- 'vmwareNetworkType', 'vmwareIpAddress', 'vmwareNetmask', 'vmwareGateway', 'vmwareNameservers',
923
- 'subnetId'
924
- ].include?(opt['fieldName'])
925
- }
926
- end
920
+ # reject old volume option types
921
+ # these will eventually get removed from the associated optionTypes
922
+ def reject_volume_option_types(option_types)
923
+ option_types.reject {|opt|
924
+ ['osDiskSize', 'osDiskType',
925
+ 'diskSize', 'diskType',
926
+ 'datastoreId', 'storagePodId'
927
+ ].include?(opt['fieldName'])
928
+ }
929
+ end
927
930
 
928
- # reject old option types that now come from the selected service plan
929
- # these will eventually get removed from the associated optionTypes
930
- def reject_service_plan_option_types(option_types)
931
- option_types.reject {|opt|
932
- ['cpuCount', 'memorySize', 'memory'].include?(opt['fieldName'])
933
- }
934
- end
931
+ # reject old networking option types
932
+ # these will eventually get removed from the associated optionTypes
933
+ def reject_networking_option_types(option_types)
934
+ option_types.reject {|opt|
935
+ ['networkId', 'networkType', 'ipAddress', 'netmask', 'gateway', 'nameservers',
936
+ 'vmwareNetworkType', 'vmwareIpAddress', 'vmwareNetmask', 'vmwareGateway', 'vmwareNameservers',
937
+ 'subnetId'
938
+ ].include?(opt['fieldName'])
939
+ }
940
+ end
935
941
 
936
- def instance_context_options
937
- [{'name' => 'Dev', 'value' => 'dev'}, {'name' => 'Test', 'value' => 'qa'}, {'name' => 'Staging', 'value' => 'staging'}, {'name' => 'Production', 'value' => 'production'}]
938
- end
942
+ # reject old option types that now come from the selected service plan
943
+ # these will eventually get removed from the associated optionTypes
944
+ def reject_service_plan_option_types(option_types)
945
+ option_types.reject {|opt|
946
+ ['cpuCount', 'memorySize', 'memory'].include?(opt['fieldName'])
947
+ }
948
+ end
939
949
 
940
- end
950
+ def instance_context_options
951
+ [{'name' => 'Dev', 'value' => 'dev'}, {'name' => 'Test', 'value' => 'qa'}, {'name' => 'Staging', 'value' => 'staging'}, {'name' => 'Production', 'value' => 'production'}]
952
+ end
953
+
954
+ end
@@ -58,7 +58,7 @@ module Morpheus
58
58
  if cur_namespace.key?(option_type['fieldName'])
59
59
  value = cur_namespace[option_type['fieldName']]
60
60
  if option_type['type'] == 'number'
61
- value = value.to_i
61
+ value = value.to_s.include?('.') ? value.to_f : value.to_i
62
62
  elsif option_type['type'] == 'select'
63
63
  # this should just fall down through below, with the extra params no_prompt, use_value
64
64
  value = select_prompt(option_type, api_client, api_params, true, value)
@@ -70,7 +70,7 @@ module Morpheus
70
70
  if value_found == false && options.key?(option_type['fieldName'])
71
71
  value = options[option_type['fieldName']]
72
72
  if option_type['type'] == 'number'
73
- value = value.to_i
73
+ value = value.to_s.include?('.') ? value.to_f : value.to_i
74
74
  end
75
75
  value_found = true
76
76
  end
@@ -81,7 +81,7 @@ module Morpheus
81
81
  no_prompt = no_prompt || options[:no_prompt]
82
82
  if no_prompt
83
83
  if !value_found
84
- if option_type['defaultValue']
84
+ if option_type['defaultValue'] != nil
85
85
  value = option_type['defaultValue']
86
86
  value_found = true
87
87
  end
@@ -196,7 +196,8 @@ module Morpheus
196
196
  while !value_found do
197
197
  print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{option_type['defaultValue'] ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
198
198
  input = $stdin.gets.chomp!
199
- value = input.empty? ? option_type['defaultValue'] : input.to_i
199
+ value = input.empty? ? option_type['defaultValue'] : input
200
+ value = value.to_s.include?('.') ? value.to_f : value.to_i
200
201
  if input == '?'
201
202
  help_prompt(option_type)
202
203
  elsif !value.nil? || option_type['required'] != true
@@ -280,22 +281,38 @@ module Morpheus
280
281
  return value
281
282
  end
282
283
 
284
+ # this is a funky one, the user is prompted for yes/no
285
+ # but the return value is 'on','off',nil
286
+ # todo: maybe make this easier to use, and have the api's be flexible too..
287
+ # @param option_type [Hash] option type object with type,fieldName,fieldLabel,etc..
288
+ # @return 'on', 'off' or nil
283
289
  def self.checkbox_prompt(option_type)
284
290
  value_found = false
285
291
  value = nil
292
+ has_default = option_type['defaultValue'] != nil
293
+ default_yes = has_default ? ['on', 'true', 'yes', '1'].include?(option_type['defaultValue'].to_s.downcase) : false
286
294
  while !value_found do
287
- print "#{option_type['fieldLabel']} (yes/no) [#{option_type['defaultValue'] == 'on' ? 'yes' : 'no'}]: "
295
+ print "#{option_type['fieldLabel']} (yes/no)#{has_default ? ' ['+(default_yes ? 'yes' : 'no')+']' : ''}: "
288
296
  input = $stdin.gets.chomp!
297
+ if input == '?'
298
+ help_prompt(option_type)
299
+ next
300
+ end
289
301
  if input.downcase == 'yes'
302
+ value_found = true
290
303
  value = 'on'
291
304
  elsif input.downcase == 'no'
305
+ value_found = true
292
306
  value = 'off'
293
- else
294
- value = option_type['defaultValue']
307
+ elsif input == '' && has_default
308
+ value_found = true
309
+ value = default_yes ? 'on' : 'off'
295
310
  end
296
- if input == '?'
297
- help_prompt(option_type)
298
- elsif !value.nil? || option_type['required'] != true
311
+ if value.nil? && option_type['required']
312
+ puts "Invalid Option... Please try again."
313
+ next
314
+ end
315
+ if value.nil? && !option_type['required']
299
316
  value_found = true
300
317
  end
301
318
  end
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "2.11.0"
4
+ VERSION = "2.11.1"
5
5
  end
6
6
  end
@@ -217,15 +217,16 @@ class Morpheus::Cli::Whoami
217
217
 
218
218
  print reset,"\n"
219
219
  end
220
+ return 0
220
221
  rescue RestClient::Exception => e
221
222
  print_rest_exception(e, options)
222
- if e.response && e.response.code == 401
223
- puts "It looks like you need to login to the remote appliance [#{@appliance_name}] #{@appliance_url}"
224
- if Morpheus::Cli::OptionTypes.confirm("Would you like to login now?")
225
- return Morpheus::Cli::Login.new.login([])
226
- end
227
- end
228
- exit 1
223
+ # if e.response && e.response.code == 401
224
+ # puts "It looks like you need to login to the remote appliance [#{@appliance_name}] #{@appliance_url}"
225
+ # if Morpheus::Cli::OptionTypes.confirm("Would you like to login now?")
226
+ # return Morpheus::Cli::Login.new.login([])
227
+ # end
228
+ # end
229
+ return 1
229
230
  end
230
231
  end
231
232