morpheus-cli 6.3.0 → 6.3.2

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.
@@ -23,8 +23,8 @@ class Morpheus::Cli::NetworkServersCommand
23
23
  end
24
24
 
25
25
  def add(args)
26
- options = {}
27
- params = {}
26
+ options = {params: {}}
27
+ params = options[:params]
28
28
  ip_range_list = nil
29
29
  optparse = Morpheus::Cli::OptionParser.new do |opts|
30
30
  opts.banner = subcommand_usage("[name]")
@@ -55,18 +55,20 @@ EOT
55
55
  end
56
56
 
57
57
  # merge -O options into normally parsed options
58
- params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
58
+ #params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
59
59
 
60
60
  # construct payload
61
61
  payload = nil
62
62
  if options[:payload]
63
63
  payload = options[:payload]
64
+ payload.deep_merge!({rest_object_key => parse_passed_options(options)})
65
+ payload.deep_merge!({rest_object_key => params})
64
66
  else
65
- # prompt for network server options
66
-
67
+ payload = {}
68
+ payload.deep_merge!({rest_object_key => parse_passed_options(options)})
67
69
  # Name
68
70
  if !params['name']
69
- params['name'] = prompt_value({'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name for this network server.'}, params, options[:no_prompt])
71
+ params['name'] = prompt_value({'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name for this network server.'}, options)
70
72
  # params['name'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name for this network server.'}], params, @api_client, {}, options[:no_prompt])['name']
71
73
  end
72
74
 
@@ -93,7 +95,7 @@ EOT
93
95
  end
94
96
  network_type_code = selected_type['code']
95
97
  else
96
- network_type_code = prompt_value({'fieldName' => 'type', 'fieldLabel' => 'Network Server Type', 'type' => 'select', 'selectOptions' => network_server_type_options, 'required' => true, 'description' => 'Choose a network server type.'}, params, options[:no_prompt])
98
+ network_type_code = prompt_value({'fieldName' => 'type', 'fieldLabel' => 'Network Server Type', 'type' => 'select', 'selectOptions' => network_server_type_options, 'required' => true, 'description' => 'Choose a network server type.'}, options.merge(params))
97
99
  #network_type_code = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Network Server Type', 'type' => 'select', 'selectOptions' => network_server_type_options, 'required' => true, 'description' => 'Choose a network server type.'}], options, @api_client, {}, options[:no_prompt])['type']
98
100
  selected_type = network_server_type_options.find {|it| it['code'] == network_type_code }
99
101
  if selected_type.nil?
@@ -106,9 +108,9 @@ EOT
106
108
  # prompt options by type
107
109
  network_server_type = @network_server_types_interface.get(network_type_id.to_i)['networkServerType']
108
110
  # params['type'] = network_server_type['code']
109
- option_result = Morpheus::Cli::OptionTypes.prompt(network_server_type['optionTypes'], params.merge({:context_map => {'networkServer' => ''}}), @api_client, {}, options[:no_prompt], true)
111
+ option_result = prompt(network_server_type['optionTypes'], options.merge({:context_map => {'networkServer' => ''}}))
110
112
  params.deep_merge!(option_result)
111
- payload = {'networkServer' => params}
113
+ payload.deep_merge!({rest_object_key => params})
112
114
  end
113
115
  @network_servers_interface.setopts(options)
114
116
  if options[:dry_run]
@@ -218,6 +220,14 @@ EOT
218
220
 
219
221
  private
220
222
 
223
+ def network_server_list_key
224
+ 'networkServers'
225
+ end
226
+
227
+ def network_server_object_key
228
+ 'networkServer'
229
+ end
230
+
221
231
  # def render_response_for_get(json_response, options)
222
232
  # # load the type and show fields dynamically based on optionTypes
223
233
  # render_response(json_response, options, rest_object_key) do
@@ -0,0 +1,17 @@
1
+ require 'morpheus/cli/cli_command'
2
+ require 'morpheus/cli/commands/catalog_item_types_command'
3
+
4
+ class Morpheus::Cli::SelfServiceCommand
5
+ include Morpheus::Cli::CliCommand
6
+
7
+ set_command_name :'self-service'
8
+ set_command_description "Deprecated and replaced by catalog-item-types"
9
+
10
+ set_command_hidden
11
+
12
+ def handle(args)
13
+ print_error yellow,"[DEPRECATED] The command `self-service` is deprecated and replaced by `catalog-item-types`.",reset,"\n"
14
+ Morpheus::Cli::CatalogItemTypesCommand.new.handle(args)
15
+ end
16
+
17
+ end
@@ -308,7 +308,7 @@ EOT
308
308
  catalog_item_type = json_response[catalog_item_type_object_key]
309
309
  # need to load by id to get optionTypes
310
310
  # maybe do ?name=foo&includeOptionTypes=true
311
- if catalog_item_type['optionTypes'].nil?
311
+ if catalog_item_type['optionTypes'].nil? && catalog_item_type['form'].nil?
312
312
  catalog_item_type = find_catalog_item_type_by_id(catalog_item_type['id'])
313
313
  return [1, "catalog item type not found"] if catalog_item_type.nil?
314
314
  end
@@ -318,14 +318,25 @@ EOT
318
318
  show_columns = catalog_item_type_column_definitions
319
319
  print_description_list(show_columns, catalog_item_type)
320
320
 
321
+ form = catalog_item_type['form']
322
+ if form
323
+ # print_h2 "Configuration Options (Form: #{form['name']})"
324
+ print_h2 "Configuration Options"
325
+ form_inputs = (form['options'] || [])
326
+ if form['fieldGroups']
327
+ form['fieldGroups'].each { |field_group| form_inputs += (field_group['options'] || []) }
328
+ end
329
+ #print format_simple_option_types_table(form_inputs, options)
330
+ print format_option_types_table(form_inputs, options, 'config.customOptions')
331
+ # print reset,"\n"
332
+ else
333
+ # print cyan,"No form inputs found for this catalog item.","\n",reset
334
+ end
335
+
321
336
  if catalog_item_type['optionTypes'] && catalog_item_type['optionTypes'].size > 0
322
337
  print_h2 "Configuration Options"
323
- print as_pretty_table(catalog_item_type['optionTypes'], {
324
- "LABEL" => lambda {|it| it['fieldLabel'] },
325
- "NAME" => lambda {|it| it['fieldName'] },
326
- "TYPE" => lambda {|it| it['type'] },
327
- "REQUIRED" => lambda {|it| format_boolean it['required'] },
328
- })
338
+ #print format_simple_option_types_table(catalog_item_type['optionTypes'], options)
339
+ print format_option_types_table(catalog_item_type['optionTypes'], options, 'config.customOptions')
329
340
  else
330
341
  # print cyan,"No option types found for this catalog item.","\n",reset
331
342
  end
@@ -645,21 +656,38 @@ EOT
645
656
 
646
657
  # this is silly, need to load by id to get optionTypes
647
658
  # maybe do ?name=foo&includeOptionTypes=true
648
- if catalog_item_type['optionTypes'].nil?
659
+ if catalog_item_type['optionTypes'].nil? && catalog_item_type['form'].nil?
649
660
  catalog_item_type = find_catalog_item_type_by_id(catalog_item_type['id'])
650
661
  return [1, "catalog item type not found"] if catalog_item_type.nil?
651
662
  end
652
- catalog_option_types = catalog_item_type['optionTypes']
653
- # instead of config.customOptions just use config...
654
- catalog_option_types = catalog_option_types.collect {|it|
655
- it['fieldContext'] = 'config'
656
- it
657
- }
658
- if catalog_option_types && !catalog_option_types.empty?
659
- api_params = construct_catalog_api_params(catalog_item_type)
660
- config_prompt = Morpheus::Cli::OptionTypes.prompt(catalog_option_types, options[:options], @api_client, api_params, options[:no_prompt], false, false, true)['config']
663
+
664
+ if catalog_item_type['formType'] == 'form'
665
+ # prompt for form options
666
+ if catalog_item_type['form'].nil?
667
+ raise_command_error "No form found for catalog item type '#{catalog_item_type['name']}'"
668
+ end
669
+ # use the new PromptHelper method prompt_form()
670
+ config_prompt = prompt_form(catalog_item_type['form'], options.merge({:context_map => {'config.customOptions' => 'config'}, :api_params => construct_catalog_api_params(catalog_item_type)}))['config']
661
671
  payload[add_item_object_key].deep_merge!({'config' => config_prompt})
672
+ else
673
+ # prompt for optionTypes
674
+ catalog_option_types = catalog_item_type['optionTypes']
675
+ if catalog_option_types.nil?
676
+ #raise_command_error "No options found for catalog item type '#{catalog_item_type['name']}'"
677
+ catalog_option_types = []
678
+ end
679
+ # instead of config.customOptions just use config...
680
+ catalog_option_types = catalog_option_types.collect {|it|
681
+ it['fieldContext'] = 'config'
682
+ it
683
+ }
684
+ if catalog_option_types && !catalog_option_types.empty?
685
+ api_params = construct_catalog_api_params(catalog_item_type)
686
+ config_prompt = Morpheus::Cli::OptionTypes.prompt(catalog_option_types, options[:options], @api_client, api_params, options[:no_prompt], false, false, true)['config']
687
+ payload[add_item_object_key].deep_merge!({'config' => config_prompt})
688
+ end
662
689
  end
690
+
663
691
  if workflow_context
664
692
  payload[add_item_object_key]['context'] = workflow_context
665
693
  else
@@ -673,7 +701,7 @@ EOT
673
701
  elsif !catalog_item_type['context'].nil?
674
702
  workflow_context = catalog_item_type['context']
675
703
  end
676
- payload[add_item_object_key]['context'] = workflow_context
704
+ payload[add_item_object_key]['context'] = workflow_context if workflow_context
677
705
  end
678
706
 
679
707
  if workflow_target
@@ -981,23 +1009,35 @@ EOT
981
1009
 
982
1010
  # this is silly, need to load by id to get optionTypes
983
1011
  # maybe do ?name=foo&includeOptionTypes=true
984
- if catalog_item_type['optionTypes'].nil?
1012
+ if catalog_item_type['optionTypes'].nil? && catalog_item_type['form'].nil?
985
1013
  catalog_item_type = find_catalog_item_type_by_id(catalog_item_type['id'])
986
1014
  return [1, "catalog item type not found"] if catalog_item_type.nil?
987
1015
  end
988
- catalog_option_types = catalog_item_type['optionTypes']
989
- # instead of config.customOptions just use config...
990
- catalog_option_types = catalog_option_types.collect {|it|
991
- it['fieldContext'] = nil
992
- it['fieldContext'] = 'config'
993
- it
994
- }
995
- if catalog_option_types && !catalog_option_types.empty?
996
- api_params = construct_catalog_api_params(catalog_item_type)
997
- config_prompt = Morpheus::Cli::OptionTypes.prompt(catalog_option_types, options[:options], @api_client, api_params, options[:no_prompt], false, false, true)['config']
1016
+
1017
+ if catalog_item_type['formType'] == 'form'
1018
+ # prompt for form options
1019
+ if catalog_item_type['form'].nil?
1020
+ raise_command_error "No form found for catalog item type '#{catalog_item_type['name']}'"
1021
+ end
1022
+ # use the new PromptHelper method prompt_form()
1023
+ config_prompt = prompt_form(catalog_item_type['form'], options.merge({:context_map => {'config.customOptions' => 'config'}, :api_params => construct_catalog_api_params(catalog_item_type)}))['config']
998
1024
  item_payload.deep_merge!({'config' => config_prompt})
1025
+ else
1026
+ # prompt for optionTypes
1027
+ catalog_option_types = catalog_item_type['optionTypes']
1028
+ # instead of config.customOptions just use config...
1029
+ catalog_option_types = catalog_option_types.collect {|it|
1030
+ it['fieldContext'] = nil
1031
+ it['fieldContext'] = 'config'
1032
+ it
1033
+ }
1034
+ if catalog_option_types && !catalog_option_types.empty?
1035
+ api_params = construct_catalog_api_params(catalog_item_type)
1036
+ config_prompt = Morpheus::Cli::OptionTypes.prompt(catalog_option_types, options[:options], @api_client, api_params, options[:no_prompt], false, false, true)['config']
1037
+ item_payload.deep_merge!({'config' => config_prompt})
1038
+ end
999
1039
  end
1000
-
1040
+
1001
1041
  if workflow_context
1002
1042
  item_payload['context'] = workflow_context
1003
1043
  else
@@ -1465,7 +1505,8 @@ EOT
1465
1505
  # this should be fixed on the api side, so it automatically extracts this input from the config
1466
1506
  begin
1467
1507
  instance_type_code = nil
1468
- catalog_item_type = find_by_id(:catalog_item_type, catalog_item_type_id.to_i)
1508
+ catalog_item_type = record
1509
+ #catalog_item_type = find_by_id(:catalog_item_type, catalog_item_type_id.to_i)
1469
1510
  if catalog_item_type
1470
1511
  if catalog_item_type['type'] == 'instance'
1471
1512
  if catalog_item_type['config'] && catalog_item_type['config']['type']
@@ -847,7 +847,7 @@ EOT
847
847
  print_description_list(virtual_image_location_column_definitions, location, options)
848
848
  if volumes && !volumes.empty?
849
849
  print_h2 "Volumes", options
850
- volume_rows = location_volumes.collect do |volume|
850
+ volume_rows = volumes.collect do |volume|
851
851
  {name: volume['name'], size: Filesize.from("#{volume['rawSize']} B").pretty}
852
852
  end
853
853
  print cyan
@@ -216,9 +216,11 @@ class Morpheus::Cli::ErrorHandler
216
216
  @stderr.puts response['msg']
217
217
  end
218
218
  if response['errors']
219
- response['errors'].each do |key, value|
220
- @stderr.print "* #{key}: #{value}\n"
221
- end
219
+ # response['errors'].each do |key, value|
220
+ # @stderr.print "* #{key}: #{value}\n"
221
+ # end
222
+ # puts as_yaml(response['errors'])
223
+ @stderr.print format_rest_errors(response['errors'])
222
224
  end
223
225
  @stderr.print reset
224
226
  else
@@ -231,6 +233,19 @@ class Morpheus::Cli::ErrorHandler
231
233
  end
232
234
  end
233
235
 
236
+ def format_rest_errors(errors, context=nil)
237
+ out = ""
238
+ Hash(errors).each do |key, value|
239
+ if value.is_a?(Hash)
240
+ out << format_rest_errors(value, context ? "#{context}.#{key}" : key)
241
+ else
242
+ prefix = context ? (context + '.') : ''
243
+ out << "* #{prefix}#{key}: #{value}\n"
244
+ end
245
+ end
246
+ out
247
+ end
248
+
234
249
  def print_rest_request(req)
235
250
  @stderr.print "REQUEST"
236
251
  @stderr.print "\n"
@@ -1511,6 +1511,8 @@ module Morpheus::Cli::PrintHelper
1511
1511
  end
1512
1512
 
1513
1513
  def format_option_types_table(option_types, options={}, domain_name=nil)
1514
+ show_option_source = option_types.find {|it| !it['optionList'].to_s.empty? || !it['optionSource'].to_s.empty? }
1515
+ show_default = option_types.find {|it| !it['defaultValue'].nil? }
1514
1516
  columns = [
1515
1517
  {"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
1516
1518
  {"FIELD NAME" => lambda {|it|
@@ -1521,17 +1523,29 @@ module Morpheus::Cli::PrintHelper
1521
1523
  end
1522
1524
  } },
1523
1525
  {"TYPE" => lambda {|it| it['type'] } },
1524
- {"OPTION SOURCE" => lambda {|it|
1525
- if it['optionSourceType']
1526
+ {"REQUIRED" => lambda {|it| format_boolean it['required'] } },
1527
+ show_option_source ? {"OPTION SOURCE" => lambda {|it|
1528
+ if it['optionList']
1529
+ it['optionList']['name']
1530
+ elsif it['optionSourceType']
1526
1531
  "#{it['optionSourceType']}/#{it['optionSource']}"
1527
1532
  else
1528
1533
  "#{it['optionSource']}"
1529
1534
  end
1530
- } },
1531
- {"DEFAULT" => lambda {|it| it['defaultValue'] } },
1532
- {"REQUIRED" => lambda {|it| format_boolean it['required'] } },
1533
- ]
1535
+ } } : nil,
1536
+ show_default ? {"DEFAULT" => lambda {|it| it['defaultValue'] } } : nil,
1537
+ ].compact
1534
1538
  as_pretty_table(option_types, columns, options)
1535
1539
  end
1540
+
1541
+ def format_simple_option_types_table(option_types, options={})
1542
+ as_pretty_table(option_types, {
1543
+ "LABEL" => lambda {|it| it['fieldLabel'] },
1544
+ "NAME" => lambda {|it| it['fieldName'] },
1545
+ "TYPE" => lambda {|it| it['type'] },
1546
+ "REQUIRED" => lambda {|it| format_boolean it['required'] },
1547
+ "DEFAULT" => lambda {|it| it['defaultValue'] },
1548
+ }, options)
1549
+ end
1536
1550
 
1537
1551
  end
@@ -1,15 +1,136 @@
1
+ require 'morpheus/cli/option_types'
2
+
1
3
  # Mixin for Morpheus::Cli command classes
2
- # Provides common methods for prompting for input
4
+ # Provides common methods for prompting for option type inputs and forms.
5
+ # Prompting is delegated to the {Morpheus::Cli::OptionTypes} module
6
+ # while the provided {#prompt} simplifies the required parameters
7
+ # The command class must establish the +@api_client+ on its own.
8
+ #
3
9
  module Morpheus::Cli::PromptHelper
4
10
 
5
- # prompt for a single option type and and return the input value
6
- # @param option_type [Hash] The OptionType input record to prompt for , contians fieldName, fieldLabel, etc.
7
- # @param options [Hash] The context being constructed, checks this for the value before prompting the user for input.
8
- # @param no_prompt [Boolean] The context being constructed, checks this for the value before prompting the user for input.
9
- # @param api_params [Hash] Optional map of parameters to include in API request for select option types
10
- # @return input value for the option type, usually a string or number if the value is an ID or of type: number
11
- def prompt_value(option_type, options, no_prompt=false, api_params={})
12
- # this does not work with fieldContext, so get rid of it
13
- return Morpheus::Cli::OptionTypes.prompt([option_type.merge({'fieldContext' => nil})], options, @api_client, api_params, no_prompt)[option_type['fieldName']]
14
- end
11
+ # Prompt for a list of inputs (OptionType) and return a Hash containing
12
+ # all of the provides values. The user is prompted to provide a value
13
+ # for each input, unless the value is already set in the options.
14
+ # @param [Array, Hash] option_types the list of OptionType inputs with fieldName, fieldLabel, etc.
15
+ # A single option type Hash can be passed instead.
16
+ # @param [Hash] options the standard command options
17
+ # This map is a mixture of keys that are Symbols that provide some common
18
+ # functionality like :no_prompt, :context_map, etc.
19
+ # Any keys that are Strings get used to lookup input values, along with
20
+ # +options[:options]+ and +options[:params]+.
21
+ # The precedence for providing option values is as follows:
22
+ # 1. options['foo'] 2. options[:params]['foo'] 3. options[:options]['foo'] 4. User is prompted.
23
+ # @option options [Hash] :options map of values provided by the user via the generic -O OPTIONS switch, gets merged into the context used for providing input values
24
+ # @option options [Hash] :params map of additional values provided by the user via explicite options, gets merged into the context used for providing input values
25
+ # @option options [Hash] :no_prompt supresses prompting, use default values and error if a required input is not provided. Default is of course +false+.
26
+ # @option options [Hash] :context_map Can to change the fieldContext of the option_types, eg. :context_map => {'networkDhcpRelay' => ''}
27
+ # @option options [APIClient] :api_client The {APIClient} to use for option types that request api calls. Default is the @api_client established by the class
28
+ # @option options [Hash] :api_params Optional map of parameters to include in API request for select option types
29
+ # @option options [Boolean] :paging_enabled Enable paging if there are a lot of available options to display. Default is +false+.
30
+ # @option options [Boolean] :ignore_empty Ignore inputs that have no options, this can be used to allow prompting to continue without error if a select input has no options.
31
+ # @option options [Boolean] :skip_sort Do not sort the inputs by displayOrder, assume they are already sorted. Default is +true+.
32
+ # @return [Hash] containing the values provided for each option type, the key is the input fieldName
33
+ #
34
+ # @example Prompt for name
35
+ #
36
+ # results = prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true}], options)
37
+ # puts "Name: #{results['name']}"
38
+ #
39
+ def prompt(option_types, options={})
40
+ # option types can be passed as a single input instead of an array
41
+ option_types = option_types.is_a?(Hash) ? [option_types] : option_types #Array(option_types)
42
+ # construct options parameter for Morpheus::Cli::OptionTypes.prompt
43
+ options = construct_prompt_options(options)
44
+ # by default the @api_client established by the command is used
45
+ api_client = options.key?(:api_client) ? options[:api_client] : @api_client
46
+ api_params = options.key?(:api_params) ? options[:api_params] : {}
47
+ no_prompt = options.key?(:no_prompt) ? options[:no_prompt] : false
48
+ paging_enabled = options.key?(:paging_enabled) ? options[:paging_enabled] : true
49
+ ignore_empty = options.key?(:ignore_empty) ? options[:ignore_empty] : false
50
+ # Defaulting skip_sort to true which is the opposite of OptionTypes.prompt()
51
+ # The API handles sorting most of the time now, calling function can sort before prompting if needed
52
+ # maybe switch this later if needed, removing skip_sort would be nice though...
53
+ skip_sort = options.key?(:skip_sort) ? options[:skip_sort] : true
54
+ results = Morpheus::Cli::OptionTypes.prompt(option_types, options, api_client, api_params, no_prompt, paging_enabled, ignore_empty, skip_sort)
55
+ # trying to get rid of the need to do these compact and booleanize calls..
56
+ # for now you can use options.merge({compact: true,booleanize: true}) or modify the results yourself
57
+ results.deep_compact! if options[:compact]
58
+ results.booleanize! if options[:booleanize] # 'on' => true
59
+ return results
60
+ end
61
+
62
+ # Process 1-N inputs (OptionType) in a special 'edit mode' that supresses user interaction.
63
+ # This is used by +update+ commands where we want to process option types
64
+ # without prompting the user so that the results only contains values that are passed in explicitely as options and default values are not used.
65
+ # @see {#prompt} method for details on the supported options
66
+ #
67
+ def no_prompt(option_types, options={})
68
+ options = options.merge({:edit_mode => true, :no_prompt => true})
69
+ options.delete(:no_prompt) if options[:always_prompt] # --prompt to always prompt
70
+ return prompt(option_types, options)
71
+ end
72
+
73
+ # Prompt for a single input and return only the value
74
+ # @param [Hash] option_type the OptionType input record to prompt for, contains fieldName, fieldLabel, etc.
75
+ # @param [Hash] options the standard command options
76
+ # @see {#prompt} method for details on the supported options
77
+ # @return [String, Number, Hash, Array, nil] value provided by the options or user input, usually a string or a number or nil if no value is provided.
78
+ #
79
+ # @example Prompt for name value
80
+ #
81
+ # chosen_name = prompt_value({'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true}, options)
82
+ # puts "Chosen Name: #{chosen_name}"
83
+ #
84
+ def prompt_value(option_type, options={})
85
+ # this does not need with fieldContext, so get rid of it
86
+ # option_types = [option_type.merge({'fieldContext' => nil})]
87
+ # results = prompt(Array(option_type), options)
88
+ # return results[option_type['fieldName']]
89
+
90
+ # this works with fieldContext now, hooray
91
+ # use get_object_value() to traverse object to get the value
92
+ option_types = [option_type] # Array(option_type)
93
+ results = prompt(option_types, options)
94
+ return get_option_type_value(results, option_types.first)
95
+ end
96
+
97
+ # Process inputs of a form, prompting for its options and field groups
98
+ # @param [Hash] form the OptionTypeForm to process
99
+ # @param [Hash] options the standard command options
100
+ # @see {#prompt} method for defailts on the supported options
101
+ # @return Hash containing the values provided for each option type, the key is the fieldName
102
+ #
103
+ def prompt_form(form, options={})
104
+ form_results = {}
105
+ results = prompt(Array(form['options']), options.merge(form_results))
106
+ form_results.deep_merge!(results)
107
+ # prompt for each field group, merging results into options context as we go
108
+ Array(form['fieldGroups']).each do |field_group|
109
+ # todo: look at isCollapsible, defaultCollapsed and visibleOnCode to see if the group should
110
+ # if collapsed then just use options.merge({:no_prompt => true}) and maybe need to set :required => false ?
111
+ results = prompt(field_group['options'], options.merge(form_results))
112
+ form_results.deep_merge!(results)
113
+ end
114
+ return form_results
115
+ end
116
+
117
+ protected
118
+
119
+ # construct options parameter for Morpheus::Cli::OptionTypes.prompt
120
+ # This options Hash is a mixture of Symbols that provide some common functionality like :no_prompt, and :context_map, etc.
121
+ # String keys are used to lookup values being passed into the command in order to prevent prompting the user
122
+ # The precedence for providing option values is as follows:
123
+ # 1. options['foo'] 2. options[:params]['foo'] 3. options[:options]['foo']
124
+ #
125
+ def construct_prompt_options(options)
126
+ passed_options = Hash(options[:options]).select {|k,v| k.is_a?(String) }
127
+ params = Hash(options[:params]).select {|k,v| k.is_a?(String) }
128
+ return passed_options.deep_merge(params).deep_merge!(options)
129
+ end
130
+
131
+ def get_option_type_value(results, option_type)
132
+ field_key = [option_type['fieldContext'], option_type['fieldName']].select {|it| it && it != '' }.join('.')
133
+ get_object_value(results, field_key)
134
+ end
135
+
15
136
  end