morpheus-cli 6.2.3 → 6.3.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.
@@ -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
@@ -763,61 +763,49 @@ class Morpheus::Cli::PoliciesCommand
763
763
  params = {}
764
764
  options = {}
765
765
  optparse = Morpheus::Cli::OptionParser.new do |opts|
766
- opts.banner = subcommand_usage()
767
- build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
766
+ opts.banner = subcommand_usage("[search]")
767
+ build_standard_list_options(opts, options, [], [:search])
768
+ opts.footer = <<-EOT
769
+ Get details about a policy type.
770
+ [policy-type] is required. This is Name or ID of a policy type.
771
+ EOT
768
772
  opts.footer = "List policy types."
769
773
  end
770
774
  optparse.parse!(args)
771
-
772
- if args.count != 0
773
- print_error Morpheus::Terminal.angry_prompt
774
- puts_error "wrong number of arguments, expected 0 and got #{args.count}\n#{optparse}"
775
- return 1
776
- end
777
-
775
+ verify_args!(args:args, optparse:optparse, count:0)
776
+ # if args.count > 0
777
+ # options[:phrase] = args.join(" ")
778
+ # end
779
+ params.merge!(parse_list_options(options))
778
780
  connect(options)
779
- begin
780
- @policies_interface.setopts(options)
781
- if options[:dry_run]
782
- print_dry_run @policies_interface.dry.list_policy_types(params)
783
- return 0
784
- end
785
- json_response = @policies_interface.list_policy_types()
781
+ @policies_interface.setopts(options)
782
+ if options[:dry_run]
783
+ print_dry_run @policies_interface.dry.list_policy_types(params)
784
+ return 0
785
+ end
786
+ json_response = @policies_interface.list_policy_types(params)
787
+ render_response(json_response, options, 'policyTypes') do
786
788
  policy_types = json_response['policyTypes']
787
- if options[:json]
788
- puts as_json(json_response, options, "policyTypes")
789
- return 0
790
- elsif options[:yaml]
791
- puts as_yaml(json_response, options, "policyTypes")
792
- return 0
793
- elsif options[:csv]
794
- puts records_as_csv(policy_types, options)
795
- return 0
796
- else
797
- print_h1 "Morpheus Policy Types"
798
- rows = policy_types.collect {|policy_type|
799
- row = {
800
- id: policy_type['id'],
801
- name: policy_type['name'],
802
- code: policy_type['code'],
803
- description: policy_type['description']
804
- }
805
- row
789
+ print_h1 "Morpheus Policy Types"
790
+ rows = policy_types.collect {|policy_type|
791
+ row = {
792
+ id: policy_type['id'],
793
+ name: policy_type['name'],
794
+ code: policy_type['code'],
795
+ description: policy_type['description']
806
796
  }
807
- columns = [:id, :name]
808
- if options[:include_fields]
809
- columns = options[:include_fields]
810
- end
811
- print cyan
812
- print as_pretty_table(rows, columns, options)
813
- print_results_pagination(json_response, {:label => "policy type", :n_label => "policy types"})
814
- print reset, "\n"
797
+ row
798
+ }
799
+ columns = [:id, :name]
800
+ if options[:include_fields]
801
+ columns = options[:include_fields]
815
802
  end
816
- return 0
817
- rescue RestClient::Exception => e
818
- print_rest_exception(e, options)
819
- return 1
803
+ print cyan
804
+ print as_pretty_table(rows, columns, options)
805
+ print_results_pagination(json_response)
806
+ print reset, "\n"
820
807
  end
808
+ return 0
821
809
  end
822
810
 
823
811
  def get_type(args)
@@ -825,91 +813,54 @@ class Morpheus::Cli::PoliciesCommand
825
813
  options = {}
826
814
  optparse = Morpheus::Cli::OptionParser.new do |opts|
827
815
  opts.banner = subcommand_usage("[policy-type]")
828
- build_common_options(opts, options, [:json, :dry_run, :remote])
829
- opts.footer = "Get details about a policy type." + "\n" +
830
- "[policy-type] is required. This is ID of a policy type."
816
+ build_standard_get_options(opts, options)
817
+ opts.footer = <<-EOT
818
+ Get details about a policy type.
819
+ [policy-type] is required. This is Name or ID of a policy type.
820
+ EOT
831
821
  end
832
822
  optparse.parse!(args)
833
-
834
- if args.count != 1
835
- print_error Morpheus::Terminal.angry_prompt
836
- puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
837
- return 1
838
- end
839
-
823
+ verify_args!(args:args, optparse:optparse, count: 1)
840
824
  connect(options)
841
- begin
842
- policy_type_id = args[0].to_s
843
- @policies_interface.setopts(options)
844
- if options[:dry_run]
845
- print_dry_run @policies_interface.dry.get_policy_type(policy_type_id, params)
846
- return 0
847
- end
848
- json_response = @policies_interface.get_policy_type(policy_type_id, params)
849
- policy_type = json_response['policyType']
850
- if options[:json]
851
- puts as_json(json_response)
852
- else
853
- print_h1 "Policy Type Details"
854
- print cyan
855
- description_cols = {
856
- "ID" => 'id',
857
- "Name" => 'name',
858
- # "Description" => 'description',
859
- "Code" => 'code',
860
- "Category" => 'category',
861
- # "Load Method" => 'loadMethod',
862
- # "Enforce Method" => 'enforceMethod',
863
- # "Prepare Method" => 'prepareMethod',
864
- # "Validate Method" => 'validateMethod',
865
- "Provision Enforced" => lambda {|it| it['enforceOnProvision'] ? 'Yes' : 'No' },
866
- "Managed Enforced" => lambda {|it| it['enforceOnManaged'] ? 'Yes' : 'No' },
867
- }
868
- print_description_list(description_cols, policy_type)
869
- print reset,"\n"
870
-
871
- # show option types
872
- print_h2 "Policy Type Options"
873
- policy_type_option_types = policy_type['optionTypes']
874
- if !policy_type_option_types || policy_type_option_types.size() == 0
875
- puts "No options found for policy type"
876
- else
877
- rows = policy_type_option_types.collect {|option_type|
878
- field_str = option_type['fieldName'].to_s
879
- if !option_type['fieldContext'].to_s.empty?
880
- field_str = option_type['fieldContext'] + "." + field_str
881
- end
882
- description_str = option_type['description'].to_s
883
- if option_type['helpBlock']
884
- if description_str.empty?
885
- description_str = option_type['helpBlock']
886
- else
887
- description_str += " " + option_type['helpBlock']
888
- end
889
- end
890
- row = {
891
- #code: option_type['code'],
892
- field: field_str,
893
- type: option_type['type'],
894
- description: description_str,
895
- default: option_type['defaultValue'],
896
- required: option_type['required'] ? 'Yes' : 'No'
897
- }
898
- row
899
- }
900
- columns = [:field, :type, :description, :default, :required]
901
- print cyan
902
- print as_pretty_table(rows, columns)
903
- print reset,"\n"
904
- end
905
- return 0
906
- end
825
+ params.merge!(parse_query_options(options))
826
+ policy_type_id = args[0]
827
+ if policy_type_id.to_s !~ /\A\d{1,}\Z/
828
+ policy_type = find_policy_type_by_name_or_id(args[0])
829
+ return [1, "Policy Type not found for #{args[0]}"] if policy_type.nil?
830
+ policy_type_id = policy_type['id']
831
+ end
832
+ @policies_interface.setopts(options)
833
+ if options[:dry_run]
834
+ print_dry_run @policies_interface.dry.get_policy_type(policy_type_id, params)
907
835
  return 0
908
- rescue RestClient::Exception => e
909
- print_rest_exception(e, options)
910
- return 1
911
836
  end
912
- @policies_interface.list_policy_types
837
+ json_response = @policies_interface.get_policy_type(policy_type_id, params)
838
+ render_response(json_response, options, 'policyType') do
839
+ policy_type = json_response['policyType']
840
+ print_h1 "Policy Type Details"
841
+ print cyan
842
+ description_cols = {
843
+ "ID" => 'id',
844
+ "Name" => 'name',
845
+ # "Description" => 'description',
846
+ "Code" => 'code',
847
+ "Category" => 'category',
848
+ # "Load Method" => 'loadMethod',
849
+ # "Enforce Method" => 'enforceMethod',
850
+ # "Prepare Method" => 'prepareMethod',
851
+ # "Validate Method" => 'validateMethod',
852
+ "Provision Enforced" => lambda {|it| it['enforceOnProvision'] ? 'Yes' : 'No' },
853
+ "Managed Enforced" => lambda {|it| it['enforceOnManaged'] ? 'Yes' : 'No' },
854
+ }
855
+ print_description_list(description_cols, policy_type)
856
+ print reset,"\n"
857
+
858
+ # show option types
859
+ print_h2 "Policy Type Options"
860
+ print format_option_types_table(policy_type['optionTypes'], options, 'policy')
861
+ print reset,"\n"
862
+ end
863
+ return 0
913
864
  end
914
865
 
915
866
  private
@@ -978,9 +929,42 @@ class Morpheus::Cli::PoliciesCommand
978
929
  end
979
930
  end
980
931
 
932
+ def find_policy_type_by_name_or_id(val)
933
+ if val.to_s =~ /\A\d{1,}\Z/
934
+ return find_policy_type_by_id(val)
935
+ else
936
+ return find_policy_type_by_name(val)
937
+ end
938
+ end
939
+
940
+ def find_policy_type_by_name(name)
941
+ json_response = nil
942
+
943
+ # json_response = @policies_interface.list_policy_types({name: name.to_s})
944
+ json_response = @policies_interface.list_policy_types({max: 10000})
945
+ policy_types = json_response['policyTypes']
946
+ match_value = name.to_s.downcase
947
+ policy_types = policy_types.select {|it| it['name'].to_s.downcase == match_value || it['code'].to_s.downcase == match_value }
948
+ if policy_types.empty?
949
+ print_red_alert "Policy not found by name #{name}"
950
+ return nil
951
+ elsif policy_types.size > 1
952
+ print_red_alert "#{policy_types.size} policy types found by name or code #{name}"
953
+ # print_policies_table(policy_types, {color: red})
954
+ rows = policy_types.collect do |it|
955
+ {id: it['id'], name: it['name'], code: it['code']}
956
+ end
957
+ puts as_pretty_table(rows, [:id, :name], {color:red})
958
+ return nil
959
+ else
960
+ policy_type = policy_types[0]
961
+ return policy_type
962
+ end
963
+ end
964
+
981
965
  def find_policy_type_by_id(id)
982
966
  begin
983
- json_response = @policies_interface.get_type(id.to_s)
967
+ json_response = @policies_interface.get_policy_type(id.to_s)
984
968
  return json_response['policyType']
985
969
  rescue RestClient::Exception => e
986
970
  if e.response && e.response.code == 404
@@ -631,6 +631,8 @@ EOT
631
631
  params['authority'] = v_prompt['authority']
632
632
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2}], options[:options])
633
633
  params['description'] = v_prompt['description']
634
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'landingUrl', 'fieldLabel' => 'landingUrl', 'type' => 'text', 'displayOrder' => 3, 'description' => 'An optional override for the default landing page after login for a user.'}], options[:options])
635
+ params['landingUrl'] = v_prompt['landingUrl']
634
636
 
635
637
  if params['owner']
636
638
  if @is_master_account && has_complete_access
@@ -2479,6 +2481,7 @@ Update default workflow access for a role.
2479
2481
  [
2480
2482
  {'fieldName' => 'authority', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
2481
2483
  {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text'},
2484
+ {'fieldName' => 'landingUrl', 'fieldLabel' => 'Landing URL', 'type' => 'text', 'description' => 'An optional override for the default landing page after login for a user.'},
2482
2485
  {'fieldName' => 'roleType', 'fieldLabel' => 'Role Type', 'type' => 'select', 'selectOptions' => [{'name' => 'User Role', 'value' => 'user'}, {'name' => 'Account Role', 'value' => 'account'}], 'defaultValue' => 'user'},
2483
2486
  {'fieldName' => 'baseRole', 'fieldLabel' => 'Copy From Role', 'type' => 'text'},
2484
2487
  {'fieldName' => 'multitenant', 'fieldLabel' => 'Multitenant', 'type' => 'checkbox', 'defaultValue' => 'off', 'description' => 'A Multitenant role is automatically copied into all existing subaccounts as well as placed into a subaccount when created. Useful for providing a set of predefined roles a Customer can use'},
@@ -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
@@ -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"
@@ -131,6 +131,7 @@ module Morpheus::Cli::AccountsHelper
131
131
  "ID" => 'id',
132
132
  "Name" => 'authority',
133
133
  "Description" => 'description',
134
+ "Landing URL" => 'landingUrl',
134
135
  #"Scope" => lambda {|it| it['scope'] },
135
136
  "Type" => lambda {|it| format_role_type(it) },
136
137
  "Multitenant" => lambda {|it|
@@ -149,6 +150,7 @@ module Morpheus::Cli::AccountsHelper
149
150
  "ID" => 'id',
150
151
  "Name" => 'authority',
151
152
  "Description" => 'description',
153
+ "Landing URL" => 'landingUrl',
152
154
  "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
153
155
  "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
154
156
  }
@@ -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