morpheus-cli 2.9.3.1 → 2.9.4
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.
- checksums.yaml +4 -4
- data/lib/morpheus/api/instance_types_interface.rb +0 -22
- data/lib/morpheus/api/instances_interface.rb +8 -1
- data/lib/morpheus/api/servers_interface.rb +9 -0
- data/lib/morpheus/cli/app_templates.rb +25 -43
- data/lib/morpheus/cli/apps.rb +5 -3
- data/lib/morpheus/cli/hosts.rb +74 -8
- data/lib/morpheus/cli/instances.rb +62 -78
- data/lib/morpheus/cli/mixins/print_helper.rb +4 -0
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +134 -2
- data/lib/morpheus/cli/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7efa35bc257cb762e29ce35995cc2291e5d21e54
|
4
|
+
data.tar.gz: ca41c50847ed8ee3a5e50d7e75c773332b1b64da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
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:
|
374
|
-
|
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
|
376
|
+
:zoneId => cloud_id,
|
399
377
|
:instance => {
|
400
378
|
:name => instance_name,
|
401
379
|
:site => {
|
402
|
-
:id =>
|
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:
|
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:
|
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:
|
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:
|
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:
|
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"=>
|
495
|
-
"zoneId"=>
|
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(
|
849
|
-
option_results = @options_interface.options_for_source('clouds',{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}"
|
data/lib/morpheus/cli/apps.rb
CHANGED
@@ -27,12 +27,13 @@ class Morpheus::Cli::Apps
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def handle(args)
|
30
|
-
usage = "Usage: morpheus apps [list,
|
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
|
-
|
35
|
-
|
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|
|
data/lib/morpheus/cli/hosts.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
213
|
-
|
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(
|
530
|
-
zone_results = @clouds_interface.get({groupId:
|
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
|
-
|
127
|
+
group_id = nil
|
128
128
|
if !options[:group].nil?
|
129
|
-
|
130
|
-
if !group.nil?
|
131
|
-
groupId = group
|
132
|
-
end
|
129
|
+
group_id = find_group_by_name(options[:group])
|
133
130
|
else
|
134
|
-
|
131
|
+
group_id = @active_groups[@appliance_name.to_sym]
|
135
132
|
end
|
136
133
|
|
137
|
-
if
|
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
|
-
|
147
|
-
if
|
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
|
151
|
+
:zoneId => cloud_id,
|
155
152
|
:instance => {
|
156
153
|
:name => instance_name,
|
157
154
|
:site => {
|
158
|
-
:id =>
|
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:
|
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:
|
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
|
-
|
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
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
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
|
-
|
188
|
-
|
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
|
-
|
191
|
-
|
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:
|
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:
|
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
|
-
|
216
|
-
|
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
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
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
|
-
|
674
|
-
new_plan_id =
|
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
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
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(
|
1052
|
-
option_results = @options_interface.options_for_source('clouds',{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
|
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
|
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
|
data/lib/morpheus/cli/version.rb
CHANGED
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.
|
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-
|
13
|
+
date: 2017-02-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|