morpheus-cli 2.9.3.1 → 2.9.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 59ad606bfeda37fd17e920c117fb7c137b9a5311
4
- data.tar.gz: 53134a57f0230f128375239d942bfcdd5ebc0191
3
+ metadata.gz: 7efa35bc257cb762e29ce35995cc2291e5d21e54
4
+ data.tar.gz: ca41c50847ed8ee3a5e50d7e75c773332b1b64da
5
5
  SHA512:
6
- metadata.gz: 57818d33486bcfe687f44428fc395c6b2c8258e2bd4a1727ef35fad6d5e3aa206e602829c9b0f9668638892ebfe2154ed9232cb7ca2dc1c9d6ef4fdf8334404c
7
- data.tar.gz: 279d0d6179234c85b176678a7a5e2de383b127c4ec1bc9e16800dbf8010ee9aa66fb3ddbffba2030a78b9ab0b1ce3c2191642ce6b3c2d2f26c87df4cdb04b53e
6
+ metadata.gz: ff52228f42aca0f2caa7727e9a14f9e1004c3878d62fa5a121efff7f7b240141b9914c64ebdc060828079df1fb2fcbfcfbbbfc5fdb89568b2b4263f4302e372a
7
+ data.tar.gz: 37c3835e75478fc8b595e86486b237941798d66806aea5c8d607803cc5f49aad1715b364aa607f46a9e568ec9b8e9e1ac65d7bd70cfb8ab4407b4c78f664039b
@@ -26,26 +26,4 @@ class Morpheus::InstanceTypesInterface < Morpheus::APIClient
26
26
  JSON.parse(response.to_s)
27
27
  end
28
28
 
29
- def service_plans(layout_id, name=nil)
30
- url = "#{@base_url}/api/instance-types/service-plans/#{layout_id}"
31
- headers = { params: {}, authorization: "Bearer #{@access_token}" }
32
-
33
- if !name.nil?
34
- headers[:params][:name] = name
35
- end
36
- response = Morpheus::RestClient.execute(method: :get, url: url,
37
- timeout: 30, headers: headers, verify_ssl: false)
38
- JSON.parse(response.to_s)
39
- end
40
-
41
- def service_plan_options(service_plan_id, params)
42
- url = "#{@base_url}/api/instance-types/service-plans/#{service_plan_id}/options"
43
- headers = { params: params, authorization: "Bearer #{@access_token}" }
44
-
45
- response = Morpheus::RestClient.execute(method: :get, url: url,
46
- timeout: 30, headers: headers, verify_ssl: false)
47
- JSON.parse(response.to_s)
48
- end
49
-
50
-
51
29
  end
@@ -155,10 +155,17 @@ class Morpheus::InstancesInterface < Morpheus::APIClient
155
155
  url = "#{@base_url}/api/instances/#{id}/security-groups"
156
156
  headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
157
157
  payload = options
158
- puts "payload #{payload}"
159
158
  response = Morpheus::RestClient.execute(method: :post, url: url,
160
159
  timeout: 30, headers: headers,verify_ssl: false, payload: payload.to_json)
161
160
  JSON.parse(response.to_s)
162
161
  end
163
162
 
163
+ def service_plans(params)
164
+ url = "#{@base_url}/api/instances/service-plans"
165
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
166
+ response = Morpheus::RestClient.execute(method: :get, url: url,
167
+ timeout: 30, headers: headers, verify_ssl: false)
168
+ JSON.parse(response.to_s)
169
+ end
170
+
164
171
  end
@@ -107,4 +107,13 @@ class Morpheus::ServersInterface < Morpheus::APIClient
107
107
  timeout: 30, headers: headers, verify_ssl:false)
108
108
  JSON.parse(response.to_s)
109
109
  end
110
+
111
+ def service_plans(params)
112
+ url = "#{@base_url}/api/servers/service-plans"
113
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
114
+ response = Morpheus::RestClient.execute(method: :get, url: url,
115
+ timeout: 30, headers: headers, verify_ssl: false)
116
+ JSON.parse(response.to_s)
117
+ end
118
+
110
119
  end
@@ -22,6 +22,7 @@ class Morpheus::Cli::AppTemplates
22
22
  @api_client = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url)
23
23
  @app_templates_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).app_templates
24
24
  @groups_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).groups
25
+ @instances_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).instances
25
26
  @instance_types_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).instance_types
26
27
  @options_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).options
27
28
  end
@@ -352,40 +353,17 @@ class Morpheus::Cli::AppTemplates
352
353
  exit 1
353
354
  end
354
355
 
355
- groupId = app_template['config']['siteId']
356
- # groupId = nil
357
- # if !options[:group].nil?
358
- # group = find_group_by_name(options[:group])
359
- # if !group.nil?
360
- # groupId = group
361
- # end
362
- # else
363
- # groupId = @active_groups[@appliance_name.to_sym]
364
- # end
356
+ group_id = app_template['config']['siteId']
365
357
 
366
- if groupId.nil?
358
+ if group_id.nil?
367
359
  #puts "Group not found or specified! \n #{optparse}"
368
360
  print_red_alert("Group not found or specified for this template!")
369
361
  puts "#{optparse}"
370
362
  exit 1
371
363
  end
372
364
 
373
- cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'optionSource' => 'clouds', 'required' => true, 'description' => 'Select Cloud.'}],options[:options],@api_client,{groupId: groupId})
374
- cloud = cloud_prompt['cloud']
375
-
376
- # if options[:cloud].nil?
377
- # #puts "Cloud not specified! \n #{optparse}"
378
- # print_red_alert("Cloud not specified!")
379
- # puts "#{optparse}"
380
- # exit 1
381
- # end
382
- # cloud = find_cloud_by_name(groupId,options[:cloud])
383
- # if cloud.nil?
384
- # #puts "Cloud not found! \n #{optparse}"
385
- # #print_red_alert("Cloud not found!")
386
- # puts "#{optparse}"
387
- # exit 1
388
- # end
365
+ cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'optionSource' => 'clouds', 'required' => true, 'description' => 'Select Cloud.'}],options[:options],@api_client,{groupId: group_id})
366
+ cloud_id = cloud_prompt['cloud']
389
367
 
390
368
 
391
369
  instance_option_types = [{'fieldName' => 'name', 'fieldLabel' => 'Instance Name', 'type' => 'text'}]
@@ -395,11 +373,11 @@ class Morpheus::Cli::AppTemplates
395
373
  # copied from instances command, this payload isn't used
396
374
  payload = {
397
375
  :servicePlan => nil,
398
- zoneId: cloud,
376
+ :zoneId => cloud_id,
399
377
  :instance => {
400
378
  :name => instance_name,
401
379
  :site => {
402
- :id => groupId
380
+ :id => group_id
403
381
  },
404
382
  :instanceType => {
405
383
  :code => instance_type_code
@@ -407,22 +385,26 @@ class Morpheus::Cli::AppTemplates
407
385
  }
408
386
  }
409
387
 
410
- version_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'version', 'type' => 'select', 'fieldLabel' => 'Version', 'optionSource' => 'instanceVersions', 'required' => true, 'skipSingleOption' => true, 'description' => 'Select which version of the instance type to be provisioned.'}],options[:options],@api_client,{groupId: groupId, cloudId: cloud, instanceTypeId: instance_type['id']})
411
- layout_prompt = 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.'}],options[:options],@api_client,{groupId: groupId, cloudId: cloud, instanceTypeId: instance_type['id'], version: version_prompt['version']})
388
+ version_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'version', 'type' => 'select', 'fieldLabel' => 'Version', 'optionSource' => 'instanceVersions', 'required' => true, 'skipSingleOption' => true, 'description' => 'Select which version of the instance type to be provisioned.'}],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id']})
389
+ layout_prompt = 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.'}],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
412
390
  layout_id = layout_prompt['layout']
413
- plan_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'servicePlan', 'type' => 'select', 'fieldLabel' => 'Plan', 'optionSource' => 'instanceServicePlans', 'required' => true, 'description' => 'Choose the appropriately sized plan for this instance'}],options[:options],@api_client,{groupId: groupId, zoneId: cloud, instanceTypeId: instance_type['id'], layoutId: layout_id, version: version_prompt['version']})
414
- payload[:servicePlan] = plan_prompt['servicePlan']
415
-
416
391
  layout = instance_type['instanceTypeLayouts'].find{ |lt| lt['id'].to_i == layout_id.to_i}
417
- instance_type['instanceTypeLayouts'].sort! { |x,y| y['sortOrder'] <=> x['sortOrder'] }
418
-
419
392
  payload[:instance][:layout] = {id: layout['id']}
420
393
 
394
+ # prompt for service plan
395
+ service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, layoutId: layout_id})
396
+ service_plans = service_plans_json["plans"]
397
+ service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"]} } # already sorted
398
+ 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'}],options[:options])
399
+ service_plan = service_plans.find {|sp| sp["id"] == plan_prompt['servicePlan'].to_i }
400
+ payload[:servicePlan] = service_plan["id"]
401
+
402
+
421
403
  type_payload = {}
422
404
  if !layout['optionTypes'].nil? && !layout['optionTypes'].empty?
423
- type_payload = Morpheus::Cli::OptionTypes.prompt(layout['optionTypes'],options[:options],@api_client,{groupId: groupId, cloudId: cloud, zoneId: cloud, instanceTypeId: instance_type['id'], version: version_prompt['version']})
405
+ type_payload = Morpheus::Cli::OptionTypes.prompt(layout['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
424
406
  elsif !instance_type['optionTypes'].nil? && !instance_type['optionTypes'].empty?
425
- type_payload = Morpheus::Cli::OptionTypes.prompt(instance_type['optionTypes'],options[:options],@api_client,{groupId: groupId, cloudId: cloud, zoneId: cloud, instanceTypeId: instance_type['id'], version: version_prompt['version']})
407
+ type_payload = Morpheus::Cli::OptionTypes.prompt(instance_type['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
426
408
  end
427
409
  if !type_payload['config'].nil?
428
410
  payload.merge!(type_payload['config'])
@@ -431,7 +413,7 @@ class Morpheus::Cli::AppTemplates
431
413
  provision_payload = {}
432
414
  if !layout['provisionType'].nil? && !layout['provisionType']['optionTypes'].nil? && !layout['provisionType']['optionTypes'].empty?
433
415
  puts "Checking for option Types"
434
- provision_payload = Morpheus::Cli::OptionTypes.prompt(layout['provisionType']['optionTypes'],options[:options],@api_client,{groupId: groupId, cloudId: cloud, zoneId: cloud, instanceTypeId: instance_type['id'], version: version_prompt['version']})
416
+ provision_payload = Morpheus::Cli::OptionTypes.prompt(layout['provisionType']['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
435
417
  end
436
418
 
437
419
  if !provision_payload.nil? && !provision_payload['config'].nil?
@@ -491,8 +473,8 @@ class Morpheus::Cli::AppTemplates
491
473
  # "volumes.storageType": nil,
492
474
 
493
475
  "version"=>version_prompt['version'],
494
- "siteId"=>groupId.to_s,
495
- "zoneId"=>cloud.to_s
476
+ "siteId"=>group_id.to_s,
477
+ "zoneId"=>cloud_id.to_s
496
478
  },
497
479
  "grabbable"=>true, "group"=>"nodes", "locked"=>false,
498
480
  #"position"=>{"x"=>-79.83254449505226, "y"=>458.33806818181824},
@@ -845,8 +827,8 @@ private
845
827
  return group_results['groups'][0]
846
828
  end
847
829
 
848
- def find_cloud_by_name(groupId,name)
849
- option_results = @options_interface.options_for_source('clouds',{groupId: groupId})
830
+ def find_cloud_by_name(group_id, name)
831
+ option_results = @options_interface.options_for_source('clouds',{groupId: group_id})
850
832
  match = option_results['data'].find { |grp| grp['value'].to_s == name.to_s || grp['name'].downcase == name.downcase}
851
833
  if match.nil?
852
834
  print_red_alert "Cloud not found by name #{name}"
@@ -27,12 +27,13 @@ class Morpheus::Cli::Apps
27
27
  end
28
28
 
29
29
  def handle(args)
30
- usage = "Usage: morpheus apps [list,add,remove,stop,start,restart,resize,upgrade,clone,envs,setenv,delenv,firewall_disable,firewall_enable,security_groups,apply_security_groups] [name]"
30
+ usage = "Usage: morpheus apps [list,remove,stop,start,restart,resize,upgrade,clone,envs,setenv,delenv,firewall_disable,firewall_enable,security_groups,apply_security_groups] [name]"
31
31
  case args[0]
32
32
  when 'list'
33
33
  list(args[1..-1])
34
- when 'add'
35
- add(args[1..-1])
34
+ # JD: this has never worked, it is time to implement it!
35
+ # when 'add'
36
+ # add(args[1..-1])
36
37
  when 'remove'
37
38
  remove(args[1..-1])
38
39
  when 'stop'
@@ -101,6 +102,7 @@ class Morpheus::Cli::Apps
101
102
  }
102
103
  }
103
104
 
105
+ # JD: this is old and busted.. appTypeLayouts is not returned..
104
106
  instance_type['appTypeLayouts'].sort! { |x,y| y['sortOrder'] <=> x['sortOrder'] }
105
107
  puts "Configurations: "
106
108
  instance_type['appTypeLayouts'].each_with_index do |layout, index|
@@ -3,11 +3,13 @@ require 'io/console'
3
3
  require 'rest_client'
4
4
  require 'optparse'
5
5
  require 'morpheus/cli/cli_command'
6
+ require 'morpheus/cli/mixins/provisioning_helper'
6
7
  require 'morpheus/cli/option_types'
7
8
  require 'json'
8
9
 
9
10
  class Morpheus::Cli::Hosts
10
11
  include Morpheus::Cli::CliCommand
12
+ include Morpheus::Cli::ProvisioningHelper
11
13
 
12
14
  def initialize()
13
15
  @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
@@ -165,7 +167,7 @@ class Morpheus::Cli::Hosts
165
167
  opts.on( '-t', '--type TYPE', "Server Type" ) do |server_type|
166
168
  options[:server_type] = server_type
167
169
  end
168
- build_common_options(opts, options, [:options, :json, :remote])
170
+ build_common_options(opts, options, [:options, :json, :dry_run, :remote])
169
171
  end
170
172
  if args.count < 2
171
173
  puts "\n#{optparse}\n\n"
@@ -180,7 +182,7 @@ class Morpheus::Cli::Hosts
180
182
  zone=nil
181
183
  if !options[:zone].nil?
182
184
  zone = find_zone_by_name(nil, options[:zone])
183
- options[:params][:zoneId] = zone['id']
185
+ options[:params][:zoneId] = zone['id'] if zone
184
186
  end
185
187
 
186
188
  if zone.nil?
@@ -190,7 +192,7 @@ class Morpheus::Cli::Hosts
190
192
  zone_type = cloud_type_for_id(zone['zoneTypeId'])
191
193
  end
192
194
 
193
- cloud_server_types = zone_type['serverTypes'].select{|b| b['creatable'] == true }
195
+ cloud_server_types = zone_type['serverTypes'].select{|b| b['creatable'] == true }.sort { |x,y| x['displayOrder'] <=> y['displayOrder'] }
194
196
  if options[:server_type]
195
197
  server_type_code = options[:server_type]
196
198
  else
@@ -206,11 +208,75 @@ class Morpheus::Cli::Hosts
206
208
  exit 1
207
209
  end
208
210
 
209
- params = Morpheus::Cli::OptionTypes.prompt(server_type['optionTypes'],options[:options],@api_client, options[:params])
211
+ payload = {}
212
+
213
+ # prompt for service plan
214
+ service_plans_json = @servers_interface.service_plans({zoneId: zone['id'], serverTypeId: server_type["id"]})
215
+ service_plans = service_plans_json["plans"]
216
+ service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"]} } # already sorted
217
+ 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 server'}],options[:options])
218
+ service_plan = service_plans.find {|sp| sp["id"] == plan_prompt['servicePlan'].to_i }
219
+ # payload[:servicePlan] = plan_prompt['servicePlan']
220
+
221
+ # prompt for volumes
222
+ volumes = prompt_volumes(service_plan, options, @api_client, {})
223
+ if !volumes.empty?
224
+ payload[:volumes] = volumes
225
+ end
226
+
227
+ # prompt for network interfaces (if supported)
228
+ if server_type["provisionType"] && server_type["provisionType"]["id"] && server_type["provisionType"]["hasNetworks"]
229
+ begin
230
+ network_interfaces = prompt_network_interfaces(zone['id'], server_type["provisionType"]["id"], options, @api_client)
231
+ if !network_interfaces.empty?
232
+ payload[:networkInterfaces] = network_interfaces
233
+ end
234
+ rescue RestClient::Exception => e
235
+ print_yellow_warning "Unable to load network options. Proceeding..."
236
+ print_rest_exception(e, options) if Morpheus::Logging.print_stacktrace?
237
+ end
238
+ end
239
+
240
+ server_type_option_types = server_type['optionTypes']
241
+ # remove volume options if volumes were configured
242
+ if !payload[:volumes].empty?
243
+ server_type_option_types = reject_volume_option_types(server_type_option_types)
244
+ end
245
+ # remove networkId option if networks were configured above
246
+ if !payload[:networkInterfaces].empty?
247
+ server_type_option_types = reject_networking_option_types(server_type_option_types)
248
+ end
249
+ # remove cpu and memory option types, which now come from the plan
250
+ server_type_option_types = reject_service_plan_option_types(server_type_option_types)
251
+
252
+ params = Morpheus::Cli::OptionTypes.prompt(server_type_option_types,options[:options],@api_client, options[:params])
210
253
  begin
211
254
  params['server'] = params['server'] || {}
212
- server_payload = {server: {name: name, zone: {id: zone['id']}, computeServerType: [id: server_type['id']]}.merge(params['server']), config: params['config'], network: params['network']}
213
- json_response = @servers_interface.create(server_payload)
255
+ payload = payload.merge({
256
+ server: {
257
+ name: name,
258
+ zone: {id: zone['id']},
259
+ computeServerType: {id: server_type['id']},
260
+ plan: {id: service_plan["id"]}
261
+ }.merge(params['server'])
262
+ })
263
+ payload[:network] = params['network'] if params['network']
264
+ payload[:config] = params['config'] if params['config']
265
+ if options[:dry_run]
266
+ print "\n" ,cyan, bold, "DRY RUN\n","==================", "\n\n", reset
267
+ print cyan
268
+ print "Request: ", "\n"
269
+ print reset
270
+ print "POST #{@appliance_url}/api/servers", "\n\n"
271
+ print cyan
272
+ print "JSON: ", "\n"
273
+ print reset
274
+ print JSON.pretty_generate(payload)
275
+ print "\n"
276
+ print reset
277
+ return
278
+ end
279
+ json_response = @servers_interface.create(payload)
214
280
  if options[:json]
215
281
  print JSON.pretty_generate(json_response)
216
282
  print "\n"
@@ -526,8 +592,8 @@ private
526
592
  return group_results['groups'][0]
527
593
  end
528
594
 
529
- def find_zone_by_name(groupId, name)
530
- zone_results = @clouds_interface.get({groupId: groupId, name: name})
595
+ def find_zone_by_name(group_id, name)
596
+ zone_results = @clouds_interface.get({groupId: group_id, name: name})
531
597
  if zone_results['zones'].empty?
532
598
  puts "Zone not found by name #{name}"
533
599
  return nil
@@ -124,17 +124,14 @@ class Morpheus::Cli::Instances
124
124
  if instance_type.nil?
125
125
  exit 1
126
126
  end
127
- groupId = nil
127
+ group_id = nil
128
128
  if !options[:group].nil?
129
- group = find_group_by_name(options[:group])
130
- if !group.nil?
131
- groupId = group
132
- end
129
+ group_id = find_group_by_name(options[:group])
133
130
  else
134
- groupId = @active_groups[@appliance_name.to_sym]
131
+ group_id = @active_groups[@appliance_name.to_sym]
135
132
  end
136
133
 
137
- if groupId.nil?
134
+ if group_id.nil?
138
135
  puts "Group not found or specified! \n #{optparse}"
139
136
  exit 1
140
137
  end
@@ -143,19 +140,19 @@ class Morpheus::Cli::Instances
143
140
  puts "Cloud not specified! \n #{optparse}"
144
141
  exit 1
145
142
  end
146
- cloud = find_cloud_by_name(groupId,options[:cloud])
147
- if cloud.nil?
143
+ cloud_id = find_cloud_by_name(group_id, options[:cloud])
144
+ if cloud_id.nil?
148
145
  puts "Cloud not found! \n #{optparse}"
149
146
  exit 1
150
147
  end
151
148
 
152
149
  payload = {
153
150
  :servicePlan => nil,
154
- zoneId: cloud,
151
+ :zoneId => cloud_id,
155
152
  :instance => {
156
153
  :name => instance_name,
157
154
  :site => {
158
- :id => groupId
155
+ :id => group_id
159
156
  },
160
157
  :instanceType => {
161
158
  :code => instance_type_code
@@ -163,48 +160,45 @@ class Morpheus::Cli::Instances
163
160
  }
164
161
  }
165
162
 
166
- version_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'version', 'type' => 'select', 'fieldLabel' => 'Version', 'optionSource' => 'instanceVersions', 'required' => true, 'skipSingleOption' => true, 'description' => 'Select which version of the instance type to be provisioned.'}],options[:options],@api_client,{groupId: groupId, cloudId: cloud, instanceTypeId: instance_type['id']})
167
- layout_prompt = 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.'}],options[:options],@api_client,{groupId: groupId, cloudId: cloud, instanceTypeId: instance_type['id'], version: version_prompt['version']})
163
+ version_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'version', 'type' => 'select', 'fieldLabel' => 'Version', 'optionSource' => 'instanceVersions', 'required' => true, 'skipSingleOption' => true, 'description' => 'Select which version of the instance type to be provisioned.'}],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id']})
164
+ layout_prompt = 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.'}],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
168
165
  layout_id = layout_prompt['layout']
169
- plan_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'servicePlan', 'type' => 'select', 'fieldLabel' => 'Plan', 'optionSource' => 'instanceServicePlans', 'required' => true, 'description' => 'Choose the appropriately sized plan for this instance'}],options[:options],@api_client,{groupId: groupId, zoneId: cloud, instanceTypeId: instance_type['id'], layoutId: layout_id, version: version_prompt['version']})
170
- payload[:servicePlan] = plan_prompt['servicePlan']
171
-
172
- layout = instance_type['instanceTypeLayouts'].find{ |lt| lt['id'].to_i == layout_id.to_i}
173
- instance_type['instanceTypeLayouts'].sort! { |x,y| y['sortOrder'] <=> x['sortOrder'] }
174
-
166
+ layout = instance_type['instanceTypeLayouts'].find{ |lt| lt['id'] == layout_id.to_i}
175
167
  payload[:instance][:layout] = {id: layout['id']}
176
168
 
177
-
178
- begin
179
- service_plan_options_json = @instance_types_interface.service_plan_options(plan_prompt['servicePlan'], {cloudId: cloud, zoneId: cloud, layoutId: layout_id})
180
-
181
- # puts ""
182
- # print JSON.pretty_generate(service_plan_options_json)
183
-
184
- plan_options = service_plan_options_json['plan']
185
- volumes = prompt_instance_volumes(plan_options, options, @api_client, {})
169
+ # prompt for service plan
170
+ service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, layoutId: layout_id})
171
+ service_plans = service_plans_json["plans"]
172
+ service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"]} } # already sorted
173
+ 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'}],options[:options])
174
+ service_plan = service_plans.find {|sp| sp["id"] == plan_prompt['servicePlan'].to_i }
175
+ payload[:servicePlan] = service_plan["id"]
186
176
 
187
- # puts "VOLUMES:"
188
- # print JSON.pretty_generate(volumes)
177
+ # prompt for volumes
178
+ volumes = prompt_volumes(service_plan, options, @api_client, {})
179
+ if !volumes.empty?
180
+ payload[:volumes] = volumes
181
+ end
189
182
 
190
- if !volumes.empty?
191
- payload[:volumes] = volumes
183
+ if layout["provisionType"] && layout["provisionType"]["id"] && layout["provisionType"]["hasNetworks"]
184
+ # prompt for network interfaces (if supported)
185
+ begin
186
+ network_interfaces = prompt_network_interfaces(cloud_id, layout["provisionType"]["id"], options, @api_client)
187
+ if !network_interfaces.empty?
188
+ payload[:networkInterfaces] = network_interfaces
189
+ end
190
+ rescue RestClient::Exception => e
191
+ print_yellow_warning "Unable to load network options. Proceeding..."
192
+ print_rest_exception(e, options) if Morpheus::Logging.print_stacktrace?
192
193
  end
193
-
194
- # puts "\nexiting early...\n"
195
- # exit 1
196
-
197
- rescue RestClient::Exception => e
198
- print_red_alert "Unable to load options for selected plan."
199
- print_rest_exception(e, options)
200
- exit 1
201
194
  end
202
-
195
+
196
+
203
197
  type_payload = {}
204
198
  if !layout['optionTypes'].nil? && !layout['optionTypes'].empty?
205
- type_payload = Morpheus::Cli::OptionTypes.prompt(layout['optionTypes'],options[:options],@api_client,{groupId: groupId, cloudId: cloud, zoneId: cloud, instanceTypeId: instance_type['id'], version: version_prompt['version']})
199
+ type_payload = Morpheus::Cli::OptionTypes.prompt(layout['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
206
200
  elsif !instance_type['optionTypes'].nil? && !instance_type['optionTypes'].empty?
207
- type_payload = Morpheus::Cli::OptionTypes.prompt(instance_type['optionTypes'],options[:options],@api_client,{groupId: groupId, cloudId: cloud, zoneId: cloud, instanceTypeId: instance_type['id'], version: version_prompt['version']})
201
+ type_payload = Morpheus::Cli::OptionTypes.prompt(instance_type['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
208
202
  end
209
203
  if !type_payload['config'].nil?
210
204
  payload.merge!(type_payload['config'])
@@ -212,8 +206,16 @@ class Morpheus::Cli::Instances
212
206
 
213
207
  provision_payload = {}
214
208
  if !layout['provisionType'].nil? && !layout['provisionType']['optionTypes'].nil? && !layout['provisionType']['optionTypes'].empty?
215
- #puts "Checking for option Types"
216
- provision_payload = Morpheus::Cli::OptionTypes.prompt(layout['provisionType']['optionTypes'],options[:options],@api_client,{groupId: groupId, cloudId: cloud, zoneId: cloud, instanceTypeId: instance_type['id'], version: version_prompt['version']})
209
+ instance_type_option_types = layout['provisionType']['optionTypes']
210
+ # remove volume options if volumes were configured
211
+ if !payload[:volumes].empty?
212
+ instance_type_option_types = reject_volume_option_types(instance_type_option_types)
213
+ end
214
+ # remove networkId option if networks were configured above
215
+ if !payload[:networkInterfaces].empty?
216
+ instance_type_option_types = reject_networking_option_types(instance_type_option_types)
217
+ end
218
+ provision_payload = Morpheus::Cli::OptionTypes.prompt(instance_type_option_types,options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
217
219
  end
218
220
 
219
221
  if !provision_payload.nil? && !provision_payload['config'].nil?
@@ -660,46 +662,28 @@ class Morpheus::Cli::Instances
660
662
 
661
663
  puts "\nDue to limitations by most Guest Operating Systems, Disk sizes can only be expanded and not reduced.\nIf a smaller plan is selected, memory and CPU (if relevant) will be reduced but storage will not.\n\n"
662
664
 
663
-
664
- #plan_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'servicePlan', 'type' => 'select', 'fieldLabel' => 'Plan', 'optionSource' => 'instanceServicePlans', 'required' => true, 'description' => 'Choose the appropriately sized plan for this instance'}],options[:options],@api_client,{groupId: groupId, zoneId: cloud, instanceTypeId: instance_type['id'], layoutId: layout_id, version: version_prompt['version']})
665
- available_plans_result = @options_interface.options_for_source('instanceServicePlans',{groupId: group_id, zoneId: cloud_id, instanceTypeId: instance['instanceType']['id'], layoutId: layout_id, version: instance['instanceVersion']})
666
- available_plans = available_plans_result['data']
667
- available_plans.each do |plan|
665
+ # prompt for service plan
666
+ service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, layoutId: layout_id})
667
+ service_plans = service_plans_json["plans"]
668
+ service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"]} } # already sorted
669
+ service_plans_dropdown.each do |plan|
668
670
  if plan['value'] && plan['value'].to_i == plan_id.to_i
669
671
  plan['name'] = "#{plan['name']} (current)"
670
672
  end
671
673
  end
672
-
673
- plan_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'servicePlan', 'type' => 'select', 'fieldLabel' => 'New Plan', 'selectOptions' => available_plans, 'required' => true, 'description' => 'Choose the new plan for this instance'}],options[:options] )
674
- new_plan_id = plan_prompt['servicePlan']
674
+ 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'}],options[:options])
675
+ service_plan = service_plans.find {|sp| sp["id"] == plan_prompt['servicePlan'].to_i }
676
+ new_plan_id = service_plan["id"]
677
+ #payload[:servicePlan] = new_plan_id # ew, this api uses servicePlanId instead
675
678
  payload[:servicePlanId] = new_plan_id
676
679
 
677
680
  volumes_response = @instances_interface.volumes(instance['id'])
678
681
  current_volumes = volumes_response['volumes'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
679
682
 
680
- begin
681
- service_plan_options_json = @instance_types_interface.service_plan_options(new_plan_id, {cloudId: cloud_id, zoneId: cloud_id, layoutId: layout_id})
682
-
683
- # puts ""
684
- # print JSON.pretty_generate(service_plan_options_json)
685
-
686
- plan_options = service_plan_options_json['plan']
687
- volumes = prompt_resize_instance_volumes(current_volumes, plan_options, options, @api_client, {})
688
-
689
- # puts "VOLUMES:"
690
- # print JSON.pretty_generate(volumes)
691
-
692
- if !volumes.empty?
693
- payload[:volumes] = volumes
694
- end
695
-
696
- # puts "\nexiting early...\n"
697
- # exit 1
698
-
699
- rescue RestClient::Exception => e
700
- print_red_alert "Unable to load options for selected plan."
701
- print_rest_exception(e, options)
702
- exit 1
683
+ # prompt for volumes
684
+ volumes = prompt_resize_volumes(current_volumes, service_plan, options, @api_client, {})
685
+ if !volumes.empty?
686
+ payload[:volumes] = volumes
703
687
  end
704
688
 
705
689
  # only amazon supports this option
@@ -1048,8 +1032,8 @@ private
1048
1032
  end
1049
1033
  end
1050
1034
 
1051
- def find_cloud_by_name(groupId,name)
1052
- option_results = @options_interface.options_for_source('clouds',{groupId: groupId})
1035
+ def find_cloud_by_name(group_id, name)
1036
+ option_results = @options_interface.options_for_source('clouds',{groupId: group_id})
1053
1037
  match = option_results['data'].find { |grp| grp['value'].to_s == name.to_s || grp['name'].downcase == name.downcase}
1054
1038
  if match.nil?
1055
1039
  return nil
@@ -11,6 +11,10 @@ module Morpheus::Cli::PrintHelper
11
11
  print red, bold, "\n#{msg}\n\n", reset
12
12
  end
13
13
 
14
+ def print_yellow_warning(msg)
15
+ print yellow, bold, "\n#{msg}\n\n", reset
16
+ end
17
+
14
18
  def print_green_success(msg)
15
19
  print green, bold, "\n#{msg}\n\n", reset
16
20
  end
@@ -10,7 +10,7 @@ module Morpheus::Cli::ProvisioningHelper
10
10
 
11
11
  # This recreates the behavior of multi_disk.js
12
12
  # returns array of volumes based on service plan options (plan_info)
13
- def prompt_instance_volumes(plan_info, options={}, api_client=nil, api_params={})
13
+ def prompt_volumes(plan_info, options={}, api_client=nil, api_params={})
14
14
  #puts "Configure Volumes:"
15
15
  no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
16
16
 
@@ -203,7 +203,7 @@ module Morpheus::Cli::ProvisioningHelper
203
203
 
204
204
  # This recreates the behavior of multi_disk.js
205
205
  # returns array of volumes based on service plan options (plan_info)
206
- def prompt_resize_instance_volumes(current_volumes, plan_info, options={}, api_client=nil, api_params={})
206
+ def prompt_resize_volumes(current_volumes, plan_info, options={}, api_client=nil, api_params={})
207
207
  #puts "Configure Volumes:"
208
208
  no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
209
209
 
@@ -484,4 +484,136 @@ module Morpheus::Cli::ProvisioningHelper
484
484
  return volumes
485
485
  end
486
486
 
487
+
488
+ # This recreates the behavior of multi_networks.js
489
+ # This is used by both `instances add` and `hosts add`
490
+ # returns array of networkInterfaces based on provision type and cloud settings
491
+ def prompt_network_interfaces(zone_id, provision_type_id, options={}, api_client=nil)
492
+ #puts "Configure Networks:"
493
+ no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
494
+
495
+ network_interfaces = []
496
+
497
+ zone_network_options_json = api_client.options.options_for_source('zoneNetworkOptions', {zoneId: zone_id, provisionTypeId: provision_type_id})
498
+ # puts "zoneNetworkOptions JSON"
499
+ # puts JSON.pretty_generate(zone_network_options_json)
500
+ zone_network_data = zone_network_options_json['data'] || {}
501
+ networks = zone_network_data['networks']
502
+ network_interface_types = (zone_network_data['networkTypes'] || []).sort { |x,y| x['displayOrder'] <=> y['displayOrder'] }
503
+ enable_network_type_selection = (zone_network_data['enableNetworkTypeSelection'] == 'on' || zone_network_data['enableNetworkTypeSelection'] == true)
504
+ has_networks = zone_network_data["hasNetworks"] == true
505
+ max_networks = zone_network_data["maxNetworks"] ? zone_network_data["maxNetworks"].to_i : nil
506
+
507
+ # skip unless provision type supports networks
508
+ if !has_networks
509
+ return nil
510
+ end
511
+
512
+ # no networks available, shouldn't happen
513
+ if networks.empty?
514
+ return network_interfaces
515
+ end
516
+
517
+ network_options = []
518
+ networks.each do |opt|
519
+ if !opt.nil?
520
+ network_options << {'name' => opt['name'], 'value' => opt['id']}
521
+ end
522
+ end
523
+
524
+ network_interface_type_options = []
525
+ network_interface_types.each do |opt|
526
+ if !opt.nil?
527
+ network_interface_type_options << {'name' => opt['name'], 'value' => opt['id']}
528
+ end
529
+ end
530
+
531
+
532
+ interface_index = 1
533
+
534
+ # has_another_interface = options[:options] && options[:options]["networkInterface"]
535
+ # add_another_interface = has_another_interface || (!no_prompt)
536
+ add_another_interface = true
537
+
538
+ while add_another_interface do
539
+
540
+ # if !no_prompt
541
+ # if interface_index == 1
542
+ # puts "Configure Network Interface"
543
+ # else
544
+ # puts "Configure Network Interface #{interface_index}"
545
+ # end
546
+ # end
547
+
548
+ field_context = interface_index == 1 ? "networkInterface" : "networkInterface#{interface_index}"
549
+
550
+ network_interface = {}
551
+
552
+ # choose network
553
+ 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])
554
+ network_interface['network'] = {}
555
+ network_interface['network']['id'] = v_prompt[field_context]['networkId'].to_i
556
+
557
+ selected_network = networks.find {|it| it["id"] == network_interface['network']['id'] }
558
+
559
+ # choose network interface type
560
+ if enable_network_type_selection && !network_interface_type_options.empty?
561
+ 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])
562
+ network_interface['networkInterfaceTypeId'] = v_prompt[field_context]['networkInterfaceTypeId'].to_i
563
+ end
564
+
565
+ # choose IP unless network has a pool configured
566
+ if selected_network['pool']
567
+ puts "IP Address: Using pool '#{selected_network['pool']['name']}'" if !no_prompt
568
+ elsif selected_network['dhcpServer']
569
+ puts "IP Address: Using DHCP" if !no_prompt
570
+ else
571
+ 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])
572
+ network_interface['ipAddress'] = v_prompt[field_context]['ipAddress']
573
+ end
574
+
575
+ network_interfaces << network_interface
576
+
577
+ interface_index += 1
578
+ has_another_interface = options[:options] && options[:options]["networkInterface#{interface_index}"]
579
+ add_another_interface = has_another_interface || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another network interface?"))
580
+ if max_networks && network_interfaces.size >= max_networks
581
+ add_another_interface = false
582
+ end
583
+
584
+ end
585
+
586
+ return network_interfaces
587
+
588
+ end
589
+
590
+ # reject old volume option types
591
+ # these will eventually get removed from the associated optionTypes
592
+ def reject_volume_option_types(option_types)
593
+ option_types.reject {|opt|
594
+ ['osDiskSize', 'osDiskType',
595
+ 'diskSize', 'diskType',
596
+ 'datastoreId', 'storagePodId'
597
+ ].include?(opt['fieldName'])
598
+ }
599
+ end
600
+
601
+ # reject old networking option types
602
+ # these will eventually get removed from the associated optionTypes
603
+ def reject_networking_option_types(option_types)
604
+ option_types.reject {|opt|
605
+ ['networkId', 'networkType', 'ipAddress', 'netmask', 'gateway', 'nameservers',
606
+ 'vmwareNetworkType', 'vmwareIpAddress', 'vmwareNetmask', 'vmwareGateway', 'vmwareNameservers'
607
+ ].include?(opt['fieldName'])
608
+ }
609
+ end
610
+
611
+ # reject old option types that now come from the selected service plan
612
+ # these will eventually get removed from the associated optionTypes
613
+ def reject_service_plan_option_types(option_types)
614
+ option_types.reject {|opt|
615
+ ['cpuCount', 'memorySize', 'memory'].include?(opt['fieldName'])
616
+ }
617
+ end
618
+
487
619
  end
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "2.9.3.1"
4
+ VERSION = "2.9.4"
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: morpheus-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.3.1
4
+ version: 2.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Estes
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-01-25 00:00:00.000000000 Z
13
+ date: 2017-02-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler