morpheus-cli 5.3.2 → 5.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/accounts_interface.rb +4 -30
  4. data/lib/morpheus/api/api_client.rb +12 -0
  5. data/lib/morpheus/api/instances_interface.rb +18 -5
  6. data/lib/morpheus/api/load_balancer_pools_interface.rb +9 -0
  7. data/lib/morpheus/api/load_balancer_types_interface.rb +9 -0
  8. data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +9 -0
  9. data/lib/morpheus/api/load_balancers_interface.rb +4 -53
  10. data/lib/morpheus/api/network_routers_interface.rb +56 -0
  11. data/lib/morpheus/api/secondary_read_interface.rb +25 -0
  12. data/lib/morpheus/api/secondary_rest_interface.rb +42 -0
  13. data/lib/morpheus/api/virtual_images_interface.rb +23 -2
  14. data/lib/morpheus/cli/apps.rb +3 -2
  15. data/lib/morpheus/cli/cli_command.rb +21 -14
  16. data/lib/morpheus/cli/cli_registry.rb +55 -2
  17. data/lib/morpheus/cli/cloud_resource_pools_command.rb +169 -133
  18. data/lib/morpheus/cli/clusters.rb +51 -33
  19. data/lib/morpheus/cli/instances.rb +292 -174
  20. data/lib/morpheus/cli/invoices_command.rb +79 -99
  21. data/lib/morpheus/cli/library_cluster_layouts_command.rb +20 -0
  22. data/lib/morpheus/cli/load_balancer_types.rb +37 -0
  23. data/lib/morpheus/cli/load_balancers.rb +149 -314
  24. data/lib/morpheus/cli/log_settings_command.rb +7 -3
  25. data/lib/morpheus/cli/mixins/load_balancers_helper.rb +156 -0
  26. data/lib/morpheus/cli/mixins/print_helper.rb +11 -0
  27. data/lib/morpheus/cli/mixins/provisioning_helper.rb +123 -101
  28. data/lib/morpheus/cli/mixins/rest_command.rb +657 -0
  29. data/lib/morpheus/cli/monitoring_checks_command.rb +2 -0
  30. data/lib/morpheus/cli/network_routers_command.rb +1183 -185
  31. data/lib/morpheus/cli/networks_command.rb +194 -101
  32. data/lib/morpheus/cli/option_parser.rb +25 -17
  33. data/lib/morpheus/cli/option_types.rb +42 -45
  34. data/lib/morpheus/cli/tenants_command.rb +18 -20
  35. data/lib/morpheus/cli/vdi_pools_command.rb +4 -1
  36. data/lib/morpheus/cli/version.rb +1 -1
  37. data/lib/morpheus/cli/virtual_images.rb +249 -29
  38. data/lib/morpheus/cli.rb +1 -0
  39. data/lib/morpheus/ext/string.rb +41 -0
  40. data/lib/morpheus/formatters.rb +4 -0
  41. data/morpheus-cli.gemspec +1 -1
  42. metadata +13 -4
@@ -6,11 +6,12 @@ class Morpheus::Cli::LogSettingsCommand
6
6
 
7
7
  set_command_name :'log-settings'
8
8
 
9
- register_subcommands :get, :update
10
- register_subcommands :enable_integration, :disable_integration, :remove_integration
9
+ register_subcommands :get, :update
11
10
  register_subcommands :add_syslog_rule, :remove_syslog_rule
12
11
 
13
- set_default_subcommand :get
12
+ # these command are deprecated in 5.3.3 and can be removed
13
+ register_subcommands :enable_integration, :disable_integration, :remove_integration
14
+ set_subcommands_hidden :enable_integration, :disable_integration, :remove_integration
14
15
 
15
16
  def connect(opts)
16
17
  @api_client = establish_remote_appliance_connection(opts)
@@ -186,6 +187,7 @@ class Morpheus::Cli::LogSettingsCommand
186
187
  end
187
188
 
188
189
  def enable_integration(args)
190
+ print_error yellow,"[DEPRECATED] The command `#{command_name} enable-integration` is deprecated.",reset,"\n"
189
191
  options = {}
190
192
 
191
193
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -240,6 +242,7 @@ class Morpheus::Cli::LogSettingsCommand
240
242
  end
241
243
 
242
244
  def disable_integration(args)
245
+ print_error yellow,"[DEPRECATED] The command `#{command_name} disable-integration` is deprecated.",reset,"\n"
243
246
  options = {}
244
247
 
245
248
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -285,6 +288,7 @@ class Morpheus::Cli::LogSettingsCommand
285
288
  end
286
289
 
287
290
  def remove_integration(args)
291
+ print_error yellow,"[DEPRECATED] The command `#{command_name } remove-integration` is deprecated.",reset,"\n"
288
292
  options = {}
289
293
 
290
294
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -0,0 +1,156 @@
1
+ require 'morpheus/cli/mixins/print_helper'
2
+ require 'morpheus/cli/option_types'
3
+ require 'morpheus/rest_client'
4
+ # Mixin for Morpheus::Cli command classes
5
+ # Provides common methods for load balancer management
6
+ # including load balancers, load balancer types, virtual servers, etc.
7
+ module Morpheus::Cli::LoadBalancersHelper
8
+
9
+ def self.included(klass)
10
+ klass.send :include, Morpheus::Cli::PrintHelper
11
+ end
12
+
13
+ def load_balancers_interface
14
+ # @api_client.load_balancers
15
+ raise "#{self.class} has not defined @load_balancers_interface" if @load_balancers_interface.nil?
16
+ @load_balancers_interface
17
+ end
18
+
19
+ def load_balancer_types_interface
20
+ # @api_client.load_balancer_types
21
+ raise "#{self.class} has not defined @load_balancer_types_interface" if @load_balancer_types_interface.nil?
22
+ @load_balancer_types_interface
23
+ end
24
+
25
+ def load_balancer_object_key
26
+ 'loadBalancer'
27
+ end
28
+
29
+ def load_balancer_list_key
30
+ 'loadBalancers'
31
+ end
32
+
33
+ def load_balancer_label
34
+ 'Load Balancer'
35
+ end
36
+
37
+ def load_balancer_plural_label
38
+ 'Load Balancers'
39
+ end
40
+
41
+ def load_balancer_type_object_key
42
+ 'loadBalancerType'
43
+ end
44
+
45
+ def load_balancer_type_list_key
46
+ 'loadBalancerTypes'
47
+ end
48
+
49
+ def load_balancer_type_label
50
+ 'Load Balancer Type'
51
+ end
52
+
53
+ def load_balancer_type_plural_label
54
+ 'Load Balancer Types'
55
+ end
56
+
57
+ def find_load_balancer_by_name_or_id(val)
58
+ if val.to_s =~ /\A\d{1,}\Z/
59
+ return find_load_balancer_by_id(val)
60
+ else
61
+ return find_load_balancer_by_name(val)
62
+ end
63
+ end
64
+
65
+ def find_load_balancer_by_id(id)
66
+ begin
67
+ json_response = load_balancers_interface.get(id.to_i)
68
+ return json_response[load_balancer_object_key]
69
+ rescue RestClient::Exception => e
70
+ if e.response && e.response.code == 404
71
+ print_red_alert "Load Balancer not found by id #{id}"
72
+ else
73
+ raise e
74
+ end
75
+ end
76
+ end
77
+
78
+ def find_load_balancer_by_name(name)
79
+ lbs = load_balancers_interface.list({name: name.to_s})[load_balancer_list_key]
80
+ if lbs.empty?
81
+ print_red_alert "Load Balancer not found by name #{name}"
82
+ return nil
83
+ elsif lbs.size > 1
84
+ print_red_alert "#{lbs.size} load balancers found by name #{name}"
85
+ #print_lbs_table(lbs, {color: red})
86
+ print reset,"\n\n"
87
+ return nil
88
+ else
89
+ return lbs[0]
90
+ end
91
+ end
92
+
93
+ def get_available_load_balancer_types(refresh=false)
94
+ if !@available_load_balancer_types || refresh
95
+ @available_load_balancer_types = load_balancer_types_interface.list({max:1000})[load_balancer_type_list_key]
96
+ end
97
+ return @available_load_balancer_types
98
+ end
99
+
100
+ def load_balancer_type_for_name_or_id(val)
101
+ if val.to_s =~ /\A\d{1,}\Z/
102
+ return load_balancer_type_for_id(val)
103
+ else
104
+ return load_balancer_type_for_name(val)
105
+ end
106
+ end
107
+
108
+ def load_balancer_type_for_id(id)
109
+ return get_available_load_balancer_types().find { |z| z['id'].to_i == id.to_i}
110
+ end
111
+
112
+ def load_balancer_type_for_name(name)
113
+ return get_available_load_balancer_types().find { |z| z['name'].downcase == name.downcase || z['code'].downcase == name.downcase}
114
+ end
115
+
116
+ def find_load_balancer_type_by_name_or_id(val)
117
+ if val.to_s =~ /\A\d{1,}\Z/
118
+ return find_load_balancer_type_by_id(val)
119
+ else
120
+ return find_load_balancer_type_by_name(val)
121
+ end
122
+ end
123
+
124
+ def find_load_balancer_type_by_id(id)
125
+ begin
126
+ json_response = load_balancer_types_interface.get(id.to_i)
127
+ return json_response[load_balancer_type_object_key]
128
+ rescue RestClient::Exception => e
129
+ if e.response && e.response.code == 404
130
+ print_red_alert "Load Balancer Type not found by id #{id}"
131
+ return nil
132
+ else
133
+ raise e
134
+ end
135
+ end
136
+ end
137
+
138
+ def find_load_balancer_type_by_name(name)
139
+ json_response = load_balancer_types_interface.list({name: name.to_s})
140
+ load_balancer_types = json_response[load_balancer_type_list_key]
141
+ if load_balancer_types.empty?
142
+ print_red_alert "Load Balancer Type not found by name #{name}"
143
+ return load_balancer_types
144
+ elsif load_balancer_types.size > 1
145
+ print_red_alert "#{load_balancer_types.size} load balancer types found by name #{name}"
146
+ rows = load_balancer_types.collect do |it|
147
+ {id: it['id'], name: it['name']}
148
+ end
149
+ puts as_pretty_table(rows, [:id, :name], {color:red})
150
+ return nil
151
+ else
152
+ return load_balancer_types[0]
153
+ end
154
+ end
155
+
156
+ end
@@ -1335,4 +1335,15 @@ module Morpheus::Cli::PrintHelper
1335
1335
  parse_json_or_yaml(config, parsers)
1336
1336
  end
1337
1337
 
1338
+ def format_option_types_table(option_types, options={}, domain_name=nil)
1339
+ columns = [
1340
+ {"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
1341
+ {"FIELD NAME" => lambda {|it| [it['fieldContext'] == domain_name ? nil : it['fieldContext'], it['fieldName']].select {|it| !it.to_s.empty? }.join('.') } },
1342
+ {"TYPE" => lambda {|it| it['type'] } },
1343
+ {"DEFAULT" => lambda {|it| it['defaultValue'] } },
1344
+ {"REQUIRED" => lambda {|it| format_boolean it['required'] } },
1345
+ ]
1346
+ as_pretty_table(option_types, columns, options)
1347
+ end
1348
+
1338
1349
  end
@@ -484,7 +484,7 @@ module Morpheus::Cli::ProvisioningHelper
484
484
  if options[:instance_type_code]
485
485
  instance_type_code = options[:instance_type_code]
486
486
  else
487
- instance_type_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'type' => 'select', 'fieldLabel' => 'Type', 'optionSource' => 'instanceTypes', 'required' => true, 'description' => 'Select Instance Type.'}],options[:options],api_client,{groupId: group_id})
487
+ instance_type_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'type' => 'select', 'fieldLabel' => 'Type', 'optionSource' => 'instanceTypes', 'required' => true, 'description' => 'Select Instance Type.'}],options[:options],api_client,{groupId: group_id}, no_prompt, true)
488
488
  instance_type_code = instance_type_prompt['type']
489
489
  end
490
490
  if instance_type_code.to_s =~ /\A\d{1,}\Z/
@@ -657,13 +657,11 @@ module Morpheus::Cli::ProvisioningHelper
657
657
  version_value = default_version_value
658
658
  version_is_required = default_layout_value.nil?
659
659
  if default_layout_value.nil? && options[:options]["layout"].nil? && options[:always_prompt] != true
660
- #version_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'version', 'type' => 'select', 'fieldLabel' => 'Version', 'optionSource' => 'instanceVersions', 'required' => true, 'skipSingleOption' => true, 'autoPickOption' => true, 'description' => 'Select which version of the instance type to be provisioned.', 'defaultValue' => default_version_value}],options[:options],api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id']})
661
660
  version_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'version', 'type' => 'select', 'fieldLabel' => 'Version', 'selectOptions' => available_versions, 'required' => version_is_required, 'skipSingleOption' => true, 'autoPickOption' => true, 'description' => 'Select which version of the instance type to be provisioned.', 'defaultValue' => default_version_value}],options[:options],api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id']})
662
661
  version_value = version_prompt['version']
663
662
  end
664
663
  end
665
-
666
- layout_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'select', 'fieldLabel' => 'Layout', 'optionSource' => 'layoutsForCloud', 'required' => true, 'description' => 'Select which configuration of the instance type to be provisioned.', 'defaultValue' => default_layout_value}],options[:options],api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], version: version_value, creatable: true})['layout']
664
+ layout_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'select', 'fieldLabel' => 'Layout', 'optionSource' => 'layoutsForCloud', 'required' => true, 'description' => 'Select which configuration of the instance type to be provisioned.', 'defaultValue' => default_layout_value}],options[:options],api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], version: version_value, creatable: true}, no_prompt, true)['layout']
667
665
  end
668
666
  end
669
667
 
@@ -679,7 +677,7 @@ module Morpheus::Cli::ProvisioningHelper
679
677
  end
680
678
  layout_id = layout['id']
681
679
  payload['instance']['layout'] = {'id' => layout['id'], 'code' => layout['code']}
682
-
680
+
683
681
  # need to GET provision type for optionTypes, and other settings...
684
682
  provision_type_code = layout['provisionTypeCode'] || layout['provisionType']['code']
685
683
  provision_type = nil
@@ -693,50 +691,6 @@ module Morpheus::Cli::ProvisioningHelper
693
691
  provision_type = get_provision_type_for_zone_type(cloud['zoneType']['id'])
694
692
  end
695
693
 
696
- # prompt for service plan
697
- plan_id = nil
698
- service_plan = nil
699
- service_plans_json = instances_interface.service_plans({zoneId: cloud_id, layoutId: layout['id'], siteId: group_id})
700
- service_plans = service_plans_json["plans"]
701
- if locked_fields.include?('plan.id')
702
- plan_id = options[:options]['plan']['id'] rescue nil
703
- if plan_id.nil?
704
- plan_id = options[:options]['instance']['plan']['id'] rescue nil
705
- end
706
- service_plan = service_plans.find {|sp| sp['id'] == plan_id }
707
- else
708
- service_plan = service_plans.find {|sp| sp['id'] == options[:service_plan].to_i} if options[:service_plan]
709
-
710
- if !service_plan
711
- service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"], 'code' => sp['code']} } # already sorted
712
- default_plan = nil
713
- if payload['plan']
714
- default_plan = payload['plan']
715
- elsif payload['instance'] && payload['instance']['plan']
716
- default_plan = payload['instance']['plan']
717
- end
718
-
719
- if options[:default_plan] && service_plans_dropdown.find {|sp| [sp["name"], sp["value"].to_s, sp["code"]].include?(options[:default_plan].to_s)}
720
- default_plan_value = options[:default_plan]
721
- else
722
- default_plan_value = options[:default_plan] || (default_plan.is_a?(Hash) ? default_plan['id'] : default_plan)
723
- end
724
- plan_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'servicePlan', 'type' => 'select', 'fieldLabel' => 'Plan', 'selectOptions' => service_plans_dropdown, 'required' => true, 'description' => 'Choose the appropriately sized plan for this instance', 'defaultValue' => default_plan_value}],options[:options])
725
- plan_id = plan_prompt['servicePlan']
726
- service_plan = service_plans.find {|sp| sp["id"] == plan_id.to_i }
727
- if !service_plan
728
- print_red_alert "Plan not found by id #{plan_id}"
729
- exit 1
730
- end
731
- end
732
- #todo: consolidate these, instances api looks for instance.plan.id and apps looks for plan.id
733
- if options[:for_app]
734
- payload['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
735
- else
736
- payload['instance']['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
737
- end
738
- end
739
-
740
694
  # build config option types
741
695
  option_type_list = []
742
696
  if !layout['optionTypes'].nil? && !layout['optionTypes'].empty?
@@ -745,47 +699,112 @@ module Morpheus::Cli::ProvisioningHelper
745
699
  if !instance_type['optionTypes'].nil? && !instance_type['optionTypes'].empty?
746
700
  option_type_list += instance_type['optionTypes']
747
701
  end
748
- if !provision_type.nil? && !provision_type['optionTypes'].nil? && !provision_type['optionTypes'].empty?
749
- option_type_list += provision_type['optionTypes']
750
- end
751
702
 
752
- # prompt for resource pool
703
+ api_params = {groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_value}
704
+
753
705
  pool_id = nil
754
706
  resource_pool = nil
755
- if locked_fields.include?('config.resourcePoolId')
756
- pool_id = payload['config']['resourcePoolId'] rescue nil
757
- elsif locked_fields.include?('config.resourcePool')
758
- pool_id = payload['config']['resourcePool'] rescue nil
759
- elsif locked_fields.include?('config.azureResourceGroupId')
760
- pool_id = payload['config']['azureResourceGroupId'] rescue nil
761
- else
762
- has_zone_pools = provision_type && provision_type["id"] && provision_type["hasZonePools"]
763
- if has_zone_pools
764
- # pluck out the resourcePoolId option type to prompt for
765
- resource_pool_option_type = option_type_list.find {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
766
- option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
767
- resource_pool_options = options_interface.options_for_source('zonePools', {groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], planId: service_plan["id"], layoutId: layout["id"]})['data']
768
- resource_pool = resource_pool_options.find {|opt| opt['id'] == options[:resource_pool].to_i} if options[:resource_pool]
769
-
770
- if resource_pool
771
- pool_id = resource_pool['id']
772
- else
773
- if options[:default_resource_pool]
774
- default_resource_pool = resource_pool_options.find {|rp| rp['id'] == options[:default_resource_pool]}
707
+ service_plan = nil
708
+
709
+ prompt_service_plan = -> {
710
+ service_plans_json = instances_interface.service_plans({zoneId: cloud_id, layoutId: layout['id'], siteId: group_id}.merge(resource_pool.nil? ? {} : {'resourcePoolId' => resource_pool['id']}))
711
+ service_plans = service_plans_json["plans"]
712
+ if locked_fields.include?('plan.id')
713
+ plan_id = options[:options]['plan']['id'] rescue nil
714
+ if plan_id.nil?
715
+ plan_id = options[:options]['instance']['plan']['id'] rescue nil
716
+ end
717
+ service_plan = service_plans.find {|sp| sp['id'] == plan_id }
718
+ else
719
+ service_plan = service_plans.find {|sp| sp['id'] == options[:service_plan].to_i} if options[:service_plan]
720
+
721
+ if !service_plan
722
+ service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"], 'code' => sp['code']} } # already sorted
723
+ default_plan = nil
724
+ if payload['plan']
725
+ default_plan = payload['plan']
726
+ elsif payload['instance'] && payload['instance']['plan']
727
+ default_plan = payload['instance']['plan']
775
728
  end
776
- resource_pool_option_type ||= {'fieldContext' => 'config', 'fieldName' => 'resourcePoolId', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'selectOptions' => resource_pool_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Select resource pool.', 'defaultValue' => default_resource_pool ? default_resource_pool['name'] : nil}
777
- resource_pool_prompt = Morpheus::Cli::OptionTypes.prompt([resource_pool_option_type],options[:options],api_client,{})
778
- resource_pool_prompt.deep_compact!
779
- payload.deep_merge!(resource_pool_prompt)
780
- resource_pool = Morpheus::Cli::OptionTypes.get_last_select()
781
- if resource_pool_option_type['fieldContext'] && resource_pool_prompt[resource_pool_option_type['fieldContext']]
782
- pool_id = resource_pool_prompt[resource_pool_option_type['fieldContext']][resource_pool_option_type['fieldName']]
783
- elsif resource_pool_prompt[resource_pool_option_type['fieldName']]
784
- pool_id = resource_pool_prompt[resource_pool_option_type['fieldName']]
729
+
730
+ if options[:default_plan] && service_plans_dropdown.find {|sp| [sp["name"], sp["value"].to_s, sp["code"]].include?(options[:default_plan].to_s)}
731
+ default_plan_value = options[:default_plan]
732
+ else
733
+ default_plan_value = options[:default_plan] || (default_plan.is_a?(Hash) ? default_plan['id'] : default_plan)
734
+ end
735
+ plan_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'servicePlan', 'type' => 'select', 'fieldLabel' => 'Plan', 'selectOptions' => service_plans_dropdown, 'required' => true, 'description' => 'Choose the appropriately sized plan for this instance', 'defaultValue' => default_plan_value}],options[:options], api_client, {}, no_prompt, true)
736
+ plan_id = plan_prompt['servicePlan']
737
+ service_plan = service_plans.find {|sp| sp["id"] == plan_id.to_i }
738
+ if !service_plan
739
+ print_red_alert "Plan not found by id #{plan_id}"
740
+ exit 1
785
741
  end
786
- resource_pool ||= resource_pool_options.find {|it| it['id'] == pool_id}
787
742
  end
743
+ #todo: consolidate these, instances api looks for instance.plan.id and apps looks for plan.id
744
+ if options[:for_app]
745
+ payload['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
746
+ else
747
+ payload['instance']['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
748
+ end
749
+ end
750
+ }
751
+
752
+ prompt_resource_pool = -> {
753
+ # prompt for resource pool
754
+ if locked_fields.include?('config.resourcePoolId')
755
+ pool_id = payload['config']['resourcePoolId'] rescue nil
756
+ elsif locked_fields.include?('config.resourcePool')
757
+ pool_id = payload['config']['resourcePool'] rescue nil
758
+ elsif locked_fields.include?('config.azureResourceGroupId')
759
+ pool_id = payload['config']['azureResourceGroupId'] rescue nil
760
+ else
761
+ has_zone_pools = provision_type && provision_type["id"] && provision_type["hasZonePools"]
762
+ if has_zone_pools
763
+ # pluck out the resourcePoolId option type to prompt for
764
+ resource_pool_option_type = option_type_list.find {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
765
+ option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
766
+
767
+ resource_pool_options = options_interface.options_for_source('zonePools', {groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], layoutId: layout["id"]}.merge(service_plan.nil? ? {} : {planId: service_plan["id"]}))['data']
768
+ resource_pool = resource_pool_options.find {|opt| opt['id'] == options[:resource_pool].to_i} if options[:resource_pool]
769
+
770
+ if resource_pool
771
+ pool_id = resource_pool['id']
772
+ else
773
+ if options[:default_resource_pool]
774
+ default_resource_pool = resource_pool_options.find {|rp| rp['id'] == options[:default_resource_pool]}
775
+ end
776
+ resource_pool_option_type ||= {'fieldContext' => 'config', 'fieldName' => 'resourcePoolId', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'selectOptions' => resource_pool_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Select resource pool.', 'defaultValue' => default_resource_pool ? default_resource_pool['name'] : nil}
777
+ resource_pool_prompt = Morpheus::Cli::OptionTypes.prompt([resource_pool_option_type],options[:options],api_client,{}, no_prompt, true)
778
+ resource_pool_prompt.deep_compact!
779
+ payload.deep_merge!(resource_pool_prompt)
780
+ resource_pool = Morpheus::Cli::OptionTypes.get_last_select()
781
+ if resource_pool_option_type['fieldContext'] && resource_pool_prompt[resource_pool_option_type['fieldContext']]
782
+ pool_id = resource_pool_prompt[resource_pool_option_type['fieldContext']][resource_pool_option_type['fieldName']]
783
+ elsif resource_pool_prompt[resource_pool_option_type['fieldName']]
784
+ pool_id = resource_pool_prompt[resource_pool_option_type['fieldName']]
785
+ end
786
+ resource_pool ||= resource_pool_options.find {|it| it['id'] == pool_id}
787
+ end
788
+ end
789
+ end
790
+ }
791
+
792
+ prompt_provision_options = -> {
793
+ if !provision_type.nil? && !provision_type['optionTypes'].nil? && !provision_type['optionTypes'].empty?
794
+ option_type_list += provision_type['optionTypes'].reject {|it| (it['fieldGroup'] || '').downcase == 'provisiontype'}
795
+ provision_config_payload = Morpheus::Cli::OptionTypes.prompt(provision_type['optionTypes'].reject {|it| (it['fieldGroup'] || '').downcase != 'provisiontype'}, options[:options], @api_client, api_params, no_prompt, true)
796
+ payload.deep_merge!(provision_config_payload)
788
797
  end
798
+ }
799
+
800
+ if ['openstack', 'huawei', 'opentelekom'].include?(cloud_type['zoneType']['code'])
801
+ prompt_resource_pool.call
802
+ prompt_provision_options.call
803
+ prompt_service_plan.call
804
+ else
805
+ prompt_service_plan.call
806
+ prompt_provision_options.call
807
+ prompt_resource_pool.call
789
808
  end
790
809
 
791
810
  # remove host selection for kubernetes
@@ -858,7 +877,7 @@ module Morpheus::Cli::ProvisioningHelper
858
877
  if provision_type && provision_type["hasNetworks"]
859
878
  # prompt for network interfaces (if supported)
860
879
  begin
861
- network_interfaces = prompt_network_interfaces(cloud_id, provision_type["id"], pool_id, options)
880
+ network_interfaces = prompt_network_interfaces(cloud_id, provision_type["id"], pool_id, options.merge({:api_params => payload['config']}))
862
881
  if !network_interfaces.empty?
863
882
  payload['networkInterfaces'] = network_interfaces
864
883
  end
@@ -921,7 +940,6 @@ module Morpheus::Cli::ProvisioningHelper
921
940
  end
922
941
 
923
942
  # prompt for option types
924
- api_params = {groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_value}
925
943
  api_params['config'] = payload['config'] if payload['config']
926
944
  api_params['poolId'] = payload['config']['resourcePoolId'] if payload['config'] && payload['config']['resourcePoolId']
927
945
 
@@ -935,10 +953,21 @@ module Morpheus::Cli::ProvisioningHelper
935
953
  end
936
954
  end
937
955
 
938
- instance_config_payload = Morpheus::Cli::OptionTypes.prompt(option_type_list, options[:options], @api_client, api_params)
939
- payload.deep_merge!(instance_config_payload)
956
+ option_type_list += [
957
+ {'fieldName' => 'userGroup.id', 'fieldLabel' => 'User Group', 'fieldGroup' => 'User Config', 'type' => 'select', 'optionSource' => 'userGroups', 'displayOrder' => 0, 'fieldContext' => 'instance'},
958
+ {'fieldName' => 'hostName', 'fieldLabel' => 'Hostname', 'fieldGroup' => 'Advanced', 'type' => 'string', 'displayOrder' => 1},
959
+ {'fieldName' => 'networkDomain.id', 'fieldLabel' => 'Domain', 'fieldGroup' => 'Advanced', 'type' => 'select', 'optionSource' => 'networkDomains', 'displayOrder' => 2, 'fieldContext' => 'instance'},
960
+ {'fieldName' => 'timezone', 'fieldLabel' => 'Time Zone', 'fieldGroup' => 'Advanced', 'type' => 'select', 'optionSource' => 'timezones', 'displayOrder' => 3, 'fieldContext' => 'config'}
961
+ ]
940
962
 
941
- ## Network Options
963
+ if instance_type['hasAutoScale']
964
+ option_type_list += [
965
+ {'fieldName' => 'layoutSize', 'fieldLabel' => 'Scale Factor', 'fieldGroup' => 'Advanced', 'type' => 'number', 'defaultValue' => 1, 'displayOrder' => 0},
966
+ ]
967
+ end
968
+
969
+ instance_config_payload = Morpheus::Cli::OptionTypes.prompt(option_type_list.reject {|ot| ot['type'] == 'exposedPorts'}, options[:options], @api_client, api_params, no_prompt, true)
970
+ payload.deep_merge!(instance_config_payload)
942
971
 
943
972
  # prompt for exposed ports
944
973
  if payload['ports'].nil?
@@ -950,10 +979,6 @@ module Morpheus::Cli::ProvisioningHelper
950
979
  end
951
980
  end
952
981
 
953
- ## Advanced Options
954
-
955
- # scale factor
956
-
957
982
  # prompt for environment variables
958
983
  evars = prompt_evars(options)
959
984
  if !evars.empty?
@@ -1327,13 +1352,9 @@ module Morpheus::Cli::ProvisioningHelper
1327
1352
 
1328
1353
  field_context = "dataVolume#{volume_index}"
1329
1354
 
1330
- if no_prompt
1331
- volume_action = 'keep'
1332
- else
1333
- action_options = [{'name' => 'Modify', 'value' => 'modify'}, {'name' => 'Keep', 'value' => 'keep'}, {'name' => 'Delete', 'value' => 'delete'}]
1334
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'action', 'type' => 'select', 'fieldLabel' => "Modify/Keep/Delete volume '#{current_volume['name']}'", 'selectOptions' => action_options, 'required' => true, 'description' => 'Modify, Keep or Delete existing data volume?'}], options[:options])
1335
- volume_action = v_prompt[field_context]['action']
1336
- end
1355
+ action_options = [{'name' => 'Modify', 'value' => 'modify'}, {'name' => 'Keep', 'value' => 'keep'}, {'name' => 'Delete', 'value' => 'delete'}]
1356
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'action', 'type' => 'select', 'fieldLabel' => "Modify/Keep/Delete volume '#{current_volume['name']}'", 'selectOptions' => action_options, 'required' => true, 'defaultValue' => 'keep', 'description' => 'Modify, Keep or Delete existing data volume?'}], options[:options])
1357
+ volume_action = v_prompt[field_context]['action']
1337
1358
 
1338
1359
  if volume_action == 'delete'
1339
1360
  # deleted volume is just excluded from post params
@@ -1490,10 +1511,11 @@ module Morpheus::Cli::ProvisioningHelper
1490
1511
  #puts "Configure Networks:"
1491
1512
  no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
1492
1513
  network_interfaces = []
1493
- api_params = {zoneId: zone_id, provisionTypeId: provision_type_id}
1514
+ api_params = {zoneId: zone_id, provisionTypeId: provision_type_id}.merge(options[:api_params] || {})
1494
1515
  if pool_id.to_s =~ /\A\d{1,}\Z/
1495
1516
  api_params[:poolId] = pool_id
1496
1517
  end
1518
+
1497
1519
  zone_network_options_json = api_client.options.options_for_source('zoneNetworkOptions', api_params)
1498
1520
  # puts "zoneNetworkOptions JSON"
1499
1521
  # puts JSON.pretty_generate(zone_network_options_json)
@@ -1575,7 +1597,7 @@ module Morpheus::Cli::ProvisioningHelper
1575
1597
  default_network_value = (network_options.find {|n| n['value'] == default_network_id} || {})['name']
1576
1598
 
1577
1599
  # choose network
1578
- 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' => default_network_value}], options[:options])
1600
+ 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' => default_network_value}], options[:options], api_client, {}, no_prompt, true)
1579
1601
  network_interface['network'] = {}
1580
1602
  network_interface['network']['id'] = v_prompt[field_context]['networkId'].to_s
1581
1603
  selected_network = networks.find {|it| it["id"].to_s == network_interface['network']['id'] }