morpheus-cli 2.11.0 → 2.11.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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