morpheus-cli 4.2.6 → 4.2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +4 -0
- data/lib/morpheus/api/clouds_interface.rb +14 -0
- data/lib/morpheus/api/guidance_interface.rb +47 -0
- data/lib/morpheus/api/users_interface.rb +7 -0
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/cli/account_groups_command.rb +1 -1
- data/lib/morpheus/cli/approvals_command.rb +2 -2
- data/lib/morpheus/cli/apps.rb +26 -30
- data/lib/morpheus/cli/blueprints_command.rb +1 -1
- data/lib/morpheus/cli/budgets_command.rb +2 -2
- data/lib/morpheus/cli/change_password_command.rb +0 -1
- data/lib/morpheus/cli/cli_command.rb +19 -9
- data/lib/morpheus/cli/clouds.rb +107 -10
- data/lib/morpheus/cli/clusters.rb +12 -12
- data/lib/morpheus/cli/commands/standard/curl_command.rb +7 -0
- data/lib/morpheus/cli/deployments.rb +2 -2
- data/lib/morpheus/cli/environments_command.rb +1 -1
- data/lib/morpheus/cli/execution_request_command.rb +1 -1
- data/lib/morpheus/cli/groups.rb +1 -1
- data/lib/morpheus/cli/guidance_command.rb +529 -0
- data/lib/morpheus/cli/hosts.rb +2 -10
- data/lib/morpheus/cli/instances.rb +31 -13
- data/lib/morpheus/cli/integrations_command.rb +1 -1
- data/lib/morpheus/cli/jobs_command.rb +2 -2
- data/lib/morpheus/cli/library_container_types_command.rb +4 -4
- data/lib/morpheus/cli/library_instance_types_command.rb +3 -3
- data/lib/morpheus/cli/library_spec_templates_command.rb +1 -1
- data/lib/morpheus/cli/load_balancers.rb +2 -2
- data/lib/morpheus/cli/mixins/print_helper.rb +43 -3
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +251 -165
- data/lib/morpheus/cli/network_routers_command.rb +1 -1
- data/lib/morpheus/cli/price_sets_command.rb +2 -2
- data/lib/morpheus/cli/provisioning_licenses_command.rb +1 -1
- data/lib/morpheus/cli/remote.rb +6 -1
- data/lib/morpheus/cli/reports_command.rb +1 -1
- data/lib/morpheus/cli/security_group_rules.rb +1 -1
- data/lib/morpheus/cli/security_groups.rb +13 -5
- data/lib/morpheus/cli/service_plans_command.rb +2 -2
- data/lib/morpheus/cli/user_groups_command.rb +2 -6
- data/lib/morpheus/cli/user_settings_command.rb +31 -5
- data/lib/morpheus/cli/user_sources_command.rb +3 -3
- data/lib/morpheus/cli/users.rb +117 -90
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +2 -2
- data/lib/morpheus/cli/whitelabel_settings_command.rb +95 -15
- data/lib/morpheus/cli/wiki_command.rb +2 -2
- data/lib/morpheus/cli/workflows.rb +2 -3
- data/lib/morpheus/formatters.rb +14 -5
- metadata +4 -2
data/lib/morpheus/cli/hosts.rb
CHANGED
@@ -203,7 +203,7 @@ class Morpheus::Cli::Hosts
|
|
203
203
|
subtitles += parse_list_subtitles(options)
|
204
204
|
print_h1 title, subtitles, options
|
205
205
|
if servers.empty?
|
206
|
-
print
|
206
|
+
print cyan,"No hosts found.",reset,"\n"
|
207
207
|
else
|
208
208
|
# print_servers_table(servers)
|
209
209
|
# server returns stats in a separate key stats => {"id" => {} }
|
@@ -762,14 +762,6 @@ class Morpheus::Cli::Hosts
|
|
762
762
|
})
|
763
763
|
|
764
764
|
option_type_list = server_type['optionTypes']
|
765
|
-
# remove volume options if volumes were configured
|
766
|
-
if !payload['volumes'].empty?
|
767
|
-
option_type_list = reject_volume_option_types(option_type_list)
|
768
|
-
end
|
769
|
-
# remove networkId option if networks were configured above
|
770
|
-
if !payload['networkInterfaces'].empty?
|
771
|
-
option_type_list = reject_networking_option_types(option_type_list)
|
772
|
-
end
|
773
765
|
|
774
766
|
# remove cpu and memory option types, which now come from the plan
|
775
767
|
option_type_list = reject_service_plan_option_types(option_type_list)
|
@@ -1466,7 +1458,7 @@ class Morpheus::Cli::Hosts
|
|
1466
1458
|
else
|
1467
1459
|
print_h1 "Morpheus Server Types - Cloud: #{zone['name']}", [], options
|
1468
1460
|
if cloud_server_types.nil? || cloud_server_types.empty?
|
1469
|
-
print
|
1461
|
+
print cyan,"No server types found for the selected cloud",reset,"\n"
|
1470
1462
|
else
|
1471
1463
|
cloud_server_types.each do |server_type|
|
1472
1464
|
print cyan, "[#{server_type['code']}]".ljust(20), " - ", "#{server_type['name']}", "\n"
|
@@ -158,7 +158,7 @@ class Morpheus::Cli::Instances
|
|
158
158
|
subtitles += parse_list_subtitles(options)
|
159
159
|
print_h1 title, subtitles, options
|
160
160
|
if instances.empty?
|
161
|
-
print
|
161
|
+
print cyan,"No instances found.",reset,"\n"
|
162
162
|
else
|
163
163
|
# print_instances_table(instances)
|
164
164
|
# server returns stats in a separate key stats => {"id" => {} }
|
@@ -208,10 +208,11 @@ class Morpheus::Cli::Instances
|
|
208
208
|
:type, :version, :environment,
|
209
209
|
{:user => {:display_name => "CREATED BY", :max_width => 20}},
|
210
210
|
:nodes, {:connection => {:max_width => 30}}, :status, :cpu, :memory, :storage]
|
211
|
-
# custom pretty table columns ...
|
212
|
-
|
213
|
-
|
214
|
-
|
211
|
+
# custom pretty table columns ... this is handled in as_pretty_table now(),
|
212
|
+
# todo: remove all these.. and try to always pass rows as the json data itself..
|
213
|
+
# if options[:include_fields]
|
214
|
+
# columns = options[:include_fields]
|
215
|
+
# end
|
215
216
|
print cyan
|
216
217
|
print as_pretty_table(rows, columns, options)
|
217
218
|
print reset
|
@@ -319,6 +320,18 @@ class Morpheus::Cli::Instances
|
|
319
320
|
opts.on("--environment ENV", String, "Environment code") do |val|
|
320
321
|
options[:environment] = val.to_s
|
321
322
|
end
|
323
|
+
opts.on('--metadata LIST', String, "Metadata tags in the format 'name:value, name:value'") do |val|
|
324
|
+
options[:metadata] = val
|
325
|
+
end
|
326
|
+
opts.on('--labels LIST', String, "Labels (keywords) in the format 'foo, bar'") do |val|
|
327
|
+
#options[:tags] = val
|
328
|
+
options[:tags] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
|
329
|
+
end
|
330
|
+
opts.on('--tags LIST', String, "Tags") do |val|
|
331
|
+
#options[:tags] = val
|
332
|
+
options[:tags] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
|
333
|
+
end
|
334
|
+
opts.add_hidden_option('--tags')
|
322
335
|
opts.on("--copies NUMBER", Integer, "Number of copies to provision") do |val|
|
323
336
|
options[:copies] = val.to_i
|
324
337
|
end
|
@@ -361,7 +374,7 @@ class Morpheus::Cli::Instances
|
|
361
374
|
opts.on("--create-backup [on|off]", String, "Automation: Create Backups.") do |val|
|
362
375
|
options[:create_backup] = ['on','true','1',''].include?(val.to_s.downcase) ? 'on' : 'off'
|
363
376
|
end
|
364
|
-
opts.on("--security-groups LIST",
|
377
|
+
opts.on("--security-groups LIST", String, "Security Groups, comma sepearated list of security group IDs") do |val|
|
365
378
|
options[:security_groups] = val.split(",").collect {|s| s.strip }.select {|s| !s.to_s.empty? }
|
366
379
|
end
|
367
380
|
opts.on('--refresh [SECONDS]', String, "Refresh until status is running,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
|
@@ -490,13 +503,18 @@ class Morpheus::Cli::Instances
|
|
490
503
|
opts.on('--group GROUP', String, "Group Name or ID") do |val|
|
491
504
|
options[:group] = val
|
492
505
|
end
|
493
|
-
opts.on('--metadata LIST', String, "Metadata in the format 'name:value, name:value'") do |val|
|
506
|
+
opts.on('--metadata LIST', String, "Metadata tags in the format 'name:value, name:value'") do |val|
|
494
507
|
options[:metadata] = val
|
495
508
|
end
|
509
|
+
opts.on('--labels LIST', String, "Labels (keywords) in the format 'foo, bar'") do |val|
|
510
|
+
#params['tags'] = val
|
511
|
+
params['tags'] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
|
512
|
+
end
|
496
513
|
opts.on('--tags LIST', String, "Tags") do |val|
|
497
|
-
params['tags'] = val
|
498
|
-
|
514
|
+
#params['tags'] = val
|
515
|
+
params['tags'] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
|
499
516
|
end
|
517
|
+
opts.add_hidden_option('--tags')
|
500
518
|
opts.on('--power-schedule-type ID', String, "Power Schedule Type ID") do |val|
|
501
519
|
params['powerScheduleType'] = val == "null" ? nil : val
|
502
520
|
end
|
@@ -1286,7 +1304,7 @@ class Morpheus::Cli::Instances
|
|
1286
1304
|
"Version" => lambda {|it| it['instanceVersion'] },
|
1287
1305
|
"Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' },
|
1288
1306
|
"Environment" => 'instanceContext',
|
1289
|
-
"
|
1307
|
+
"Labels" => lambda {|it| it['tags'] ? it['tags'].join(',') : '' },
|
1290
1308
|
"Metadata" => lambda {|it| it['metadata'] ? it['metadata'].collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' },
|
1291
1309
|
"Power Schedule" => lambda {|it| (it['powerSchedule'] && it['powerSchedule']['type']) ? it['powerSchedule']['type']['name'] : '' },
|
1292
1310
|
"Created By" => lambda {|it| it['createdBy'] ? (it['createdBy']['username'] || it['createdBy']['id']) : '' },
|
@@ -1399,7 +1417,7 @@ class Morpheus::Cli::Instances
|
|
1399
1417
|
if options[:include_scaling]
|
1400
1418
|
print_h2 "Instance Scaling", options
|
1401
1419
|
if instance_threshold.nil? || instance_threshold.empty?
|
1402
|
-
print
|
1420
|
+
print cyan,"No scaling settings applied to this instance.",reset,"\n"
|
1403
1421
|
else
|
1404
1422
|
print cyan
|
1405
1423
|
print_instance_threshold_description_list(instance_threshold)
|
@@ -1476,7 +1494,7 @@ class Morpheus::Cli::Instances
|
|
1476
1494
|
title = "Instance Containers: #{instance['name']} (#{instance['instanceType']['name']})"
|
1477
1495
|
print_h1 title, [], options
|
1478
1496
|
if containers.empty?
|
1479
|
-
print
|
1497
|
+
print cyan,"No containers found for instance.",reset,"\n"
|
1480
1498
|
else
|
1481
1499
|
|
1482
1500
|
rows = containers.collect {|container|
|
@@ -3008,7 +3026,7 @@ class Morpheus::Cli::Instances
|
|
3008
3026
|
title = "Instance Scaling: [#{instance['id']}] #{instance['name']} (#{instance['instanceType']['name']})"
|
3009
3027
|
print_h1 title, [], options
|
3010
3028
|
if instance_threshold.empty?
|
3011
|
-
print
|
3029
|
+
print cyan,"No scaling settings applied to this instance.",reset,"\n"
|
3012
3030
|
else
|
3013
3031
|
# print_h1 "Threshold Settings", [], options
|
3014
3032
|
print cyan
|
@@ -53,7 +53,7 @@ class Morpheus::Cli::IntegrationsCommand
|
|
53
53
|
integrations = json_response['integrations']
|
54
54
|
|
55
55
|
if integrations.empty?
|
56
|
-
print
|
56
|
+
print cyan,"No integrations found.",reset,"\n"
|
57
57
|
else
|
58
58
|
rows = integrations.collect do |it|
|
59
59
|
{
|
@@ -79,7 +79,7 @@ class Morpheus::Cli::JobsCommand
|
|
79
79
|
jobs = json_response['jobs']
|
80
80
|
|
81
81
|
if jobs.empty?
|
82
|
-
print
|
82
|
+
print cyan,"No jobs found.",reset,"\n"
|
83
83
|
else
|
84
84
|
rows = jobs.collect do |job|
|
85
85
|
{
|
@@ -944,7 +944,7 @@ class Morpheus::Cli::JobsCommand
|
|
944
944
|
|
945
945
|
def print_job_executions(execs, options={})
|
946
946
|
if execs.empty?
|
947
|
-
print
|
947
|
+
print cyan,"No job executions found.",reset,"\n"
|
948
948
|
else
|
949
949
|
rows = execs.collect do |ex|
|
950
950
|
{
|
@@ -189,7 +189,7 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
189
189
|
]
|
190
190
|
print as_pretty_table(evars, evar_columns)
|
191
191
|
else
|
192
|
-
# print
|
192
|
+
# print cyan,"No environment variables found for this node type.","\n",reset
|
193
193
|
end
|
194
194
|
|
195
195
|
exposed_ports = container_type['containerPorts']
|
@@ -203,7 +203,7 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
203
203
|
]
|
204
204
|
print as_pretty_table(exposed_ports, columns)
|
205
205
|
else
|
206
|
-
# print
|
206
|
+
# print cyan,"No exposed ports found for this node type.","\n",reset
|
207
207
|
end
|
208
208
|
|
209
209
|
container_scripts = container_type['containerScripts'] || container_type['scripts']
|
@@ -215,7 +215,7 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
215
215
|
]
|
216
216
|
print as_pretty_table(container_scripts, columns)
|
217
217
|
else
|
218
|
-
# print
|
218
|
+
# print cyan,"No scripts found for this node type.","\n",reset
|
219
219
|
end
|
220
220
|
|
221
221
|
container_file_templates = container_type['containerTemplates'] || container_type['templates']
|
@@ -227,7 +227,7 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
227
227
|
]
|
228
228
|
print as_pretty_table(container_file_templates, columns)
|
229
229
|
else
|
230
|
-
# print
|
230
|
+
# print cyan,"No scripts found for this node type.","\n",reset
|
231
231
|
end
|
232
232
|
|
233
233
|
print reset,"\n"
|
@@ -178,7 +178,7 @@ class Morpheus::Cli::LibraryInstanceTypesCommand
|
|
178
178
|
]
|
179
179
|
print as_pretty_table(instance_type_option_types, columns)
|
180
180
|
else
|
181
|
-
# print
|
181
|
+
# print cyan,"No option types found for this layout.","\n",reset
|
182
182
|
end
|
183
183
|
|
184
184
|
instance_type_evars = instance_type['environmentVariables']
|
@@ -193,7 +193,7 @@ class Morpheus::Cli::LibraryInstanceTypesCommand
|
|
193
193
|
]
|
194
194
|
print as_pretty_table(instance_type_evars, evar_columns)
|
195
195
|
else
|
196
|
-
# print
|
196
|
+
# print cyan,"No environment variables found for this instance type.","\n",reset
|
197
197
|
end
|
198
198
|
|
199
199
|
print_h2 "Layouts"
|
@@ -229,7 +229,7 @@ class Morpheus::Cli::LibraryInstanceTypesCommand
|
|
229
229
|
]
|
230
230
|
print as_pretty_table(instance_type_layouts, layout_columns)
|
231
231
|
else
|
232
|
-
print
|
232
|
+
print cyan,"No layouts found for this instance type.","\n",reset
|
233
233
|
end
|
234
234
|
|
235
235
|
print reset,"\n"
|
@@ -56,7 +56,7 @@ class Morpheus::Cli::LoadBalancers
|
|
56
56
|
lbs = json_response['loadBalancers']
|
57
57
|
print_h1 "Morpheus Load Balancers"
|
58
58
|
if lbs.empty?
|
59
|
-
print
|
59
|
+
print cyan,"No load balancers found.",reset,"\n"
|
60
60
|
else
|
61
61
|
columns = [
|
62
62
|
{"ID" => 'id'},
|
@@ -243,7 +243,7 @@ class Morpheus::Cli::LoadBalancers
|
|
243
243
|
lb_types = json_response['loadBalancerTypes']
|
244
244
|
print_h1 "Morpheus Load Balancer Types"
|
245
245
|
if lb_types.nil? || lb_types.empty?
|
246
|
-
print
|
246
|
+
print cyan,"No load balancer types found.",reset,"\n"
|
247
247
|
else
|
248
248
|
print cyan
|
249
249
|
lb_table_data = lb_types.collect do |lb_type|
|
@@ -538,7 +538,7 @@ module Morpheus::Cli::PrintHelper
|
|
538
538
|
value = value.to_s
|
539
539
|
if do_wrap && value && Morpheus::Cli::PrintHelper.terminal_width
|
540
540
|
value_width = Morpheus::Cli::PrintHelper.terminal_width - label_width
|
541
|
-
if value_width > 0 && value.to_s.size > value_width
|
541
|
+
if value_width > 0 && value.gsub(/\e\[(\d+)m/, '').to_s.size > value_width
|
542
542
|
wrap_indent = label_width + 1 # plus 1 needs to go away
|
543
543
|
value = wrap(value, value_width, wrap_indent)
|
544
544
|
end
|
@@ -628,6 +628,44 @@ module Morpheus::Cli::PrintHelper
|
|
628
628
|
#
|
629
629
|
def as_pretty_table(data, columns, options={})
|
630
630
|
data = [data].flatten
|
631
|
+
|
632
|
+
# support --fields x,y,z and --all-fields or --fields all
|
633
|
+
all_fields = data.first ? data.first.keys : []
|
634
|
+
|
635
|
+
if options[:include_fields]
|
636
|
+
if (options[:include_fields].is_a?(Array) && options[:include_fields].size == 1 && options[:include_fields][0] == 'all') || options[:include_fields] == 'all'
|
637
|
+
columns = all_fields
|
638
|
+
else
|
639
|
+
# so let's use the passed in column definitions instead of the raw data properties
|
640
|
+
# columns = options[:include_fields]
|
641
|
+
new_columns = []
|
642
|
+
options[:include_fields].each do |f|
|
643
|
+
matching_column = nil
|
644
|
+
# column definitions vary right now, array of symbols/strings/hashes or perhaps a single hash
|
645
|
+
if columns.is_a?(Array) && columns[0] && columns[0].is_a?(Hash)
|
646
|
+
matching_column = columns.find {|c|
|
647
|
+
if c.is_a?(Hash)
|
648
|
+
c.keys[0].to_s.downcase == f.to_s.downcase
|
649
|
+
else
|
650
|
+
c && c.to_s.downcase == f.to_s.downcase
|
651
|
+
end
|
652
|
+
}
|
653
|
+
elsif columns.is_a?(Hash)
|
654
|
+
matching_key = columns.keys.find {|k| k.to_s.downcase == f.to_s.downcase }
|
655
|
+
if matching_key
|
656
|
+
matching_column = columns[matching_key]
|
657
|
+
end
|
658
|
+
end
|
659
|
+
new_columns << (matching_column ? matching_column : f)
|
660
|
+
end
|
661
|
+
columns = new_columns
|
662
|
+
end
|
663
|
+
elsif options[:all_fields]
|
664
|
+
columns = all_fields
|
665
|
+
else
|
666
|
+
columns = columns
|
667
|
+
end
|
668
|
+
|
631
669
|
columns = build_column_definitions(columns)
|
632
670
|
|
633
671
|
table_color = options[:color] || cyan
|
@@ -690,7 +728,7 @@ module Morpheus::Cli::PrintHelper
|
|
690
728
|
# could use some options[:preferred_columns] logic here to throw away in some specified order
|
691
729
|
# --all fields disables this
|
692
730
|
trimmed_columns = []
|
693
|
-
if options[:responsive_table] != false && options[:include_fields].nil? && options[:all_fields] != true
|
731
|
+
if options[:responsive_table] != false # && options[:include_fields].nil? && options[:all_fields] != true
|
694
732
|
|
695
733
|
begin
|
696
734
|
term_width = current_terminal_width()
|
@@ -1027,11 +1065,13 @@ module Morpheus::Cli::PrintHelper
|
|
1027
1065
|
cols = []
|
1028
1066
|
all_fields = records.first ? records.first.keys : []
|
1029
1067
|
if options[:include_fields]
|
1030
|
-
if options[:include_fields] == 'all' || options[:include_fields]
|
1068
|
+
if (options[:include_fields].is_a?(Array) && options[:include_fields].size == 1 && options[:include_fields][0] == 'all') || options[:include_fields] == 'all'
|
1031
1069
|
cols = all_fields
|
1032
1070
|
else
|
1033
1071
|
cols = options[:include_fields]
|
1034
1072
|
end
|
1073
|
+
elsif options[:all_fields]
|
1074
|
+
cols = all_fields
|
1035
1075
|
elsif default_columns
|
1036
1076
|
cols = default_columns
|
1037
1077
|
else
|
@@ -298,10 +298,12 @@ module Morpheus::Cli::ProvisioningHelper
|
|
298
298
|
# prompts user for all the configuartion options for a particular instance
|
299
299
|
# returns payload of data for a new instance
|
300
300
|
def prompt_new_instance(options={})
|
301
|
+
no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
|
301
302
|
#puts "prompt_new_instance() #{options}"
|
302
303
|
print reset # clear colors
|
303
304
|
options[:options] ||= {}
|
304
|
-
|
305
|
+
# provisioning with blueprint can lock fields
|
306
|
+
locked_fields = options[:locked_fields] || []
|
305
307
|
# Group
|
306
308
|
default_group = find_group_by_name_or_id_for_provisioning(options[:default_group] || @active_group_id) if options[:default_group] || @active_group_id
|
307
309
|
|
@@ -365,7 +367,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
365
367
|
instance_name = name_prompt['name']
|
366
368
|
else
|
367
369
|
print_red_alert "Name must be unique"
|
368
|
-
|
370
|
+
exit 1 if no_prompt
|
369
371
|
if options[:default_name] == name_prompt['name']
|
370
372
|
options[:default_name] += '-2'
|
371
373
|
end
|
@@ -421,6 +423,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
421
423
|
arbitrary_options.delete('environment')
|
422
424
|
arbitrary_options.delete('instanceContext')
|
423
425
|
arbitrary_options.delete('tags')
|
426
|
+
arbitrary_options.delete('lockedFields')
|
424
427
|
# arbitrary_options.delete('ports')
|
425
428
|
payload.deep_merge!(arbitrary_options)
|
426
429
|
end
|
@@ -441,68 +444,85 @@ module Morpheus::Cli::ProvisioningHelper
|
|
441
444
|
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'environment', 'fieldLabel' => 'Environment', 'type' => 'select', 'required' => false, 'selectOptions' => get_available_environments()}], options[:options])
|
442
445
|
payload['instance']['instanceContext'] = v_prompt['environment'] if !v_prompt['environment'].empty?
|
443
446
|
|
444
|
-
#
|
445
|
-
|
446
|
-
|
447
|
+
# Labels (tags)
|
448
|
+
if options[:tags]
|
449
|
+
payload['instance']['tags'] = options[:tags].is_a?(Array) ? options[:tags] : options[:tags].to_s.split(',').collect {|it| it.to_s.strip }.compact.uniq
|
450
|
+
else
|
451
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'tags', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false}], options[:options])
|
452
|
+
payload['instance']['tags'] = v_prompt['tags'].split(',').collect {|it| it.to_s.strip }.compact.uniq if !v_prompt['tags'].empty?
|
453
|
+
end
|
447
454
|
|
448
455
|
# Version and Layout
|
449
|
-
|
450
|
-
|
456
|
+
layout_id = nil
|
457
|
+
if locked_fields.include?('instance.layout.id')
|
458
|
+
layout_id = options[:options]['instance']['layout'] rescue options[:options]['layout']
|
459
|
+
if layout_id.is_a?(Hash)
|
460
|
+
layout_id = layout_id['id'] || layout_id['code'] || layout_id['name']
|
461
|
+
end
|
451
462
|
else
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
463
|
+
layout_id = nil
|
464
|
+
if options[:layout]
|
465
|
+
layout_id = options[:layout]
|
466
|
+
end
|
467
|
+
if layout_id.is_a?(Hash)
|
468
|
+
layout_id = layout_id['id'] || layout_id['code'] || layout_id['name']
|
469
|
+
end
|
470
|
+
if layout_id.nil?
|
471
|
+
version_value = nil
|
472
|
+
default_layout_value = nil
|
473
|
+
if options[:version]
|
474
|
+
version_value = options[:version]
|
475
|
+
else
|
476
|
+
available_versions = options_interface.options_for_source('instanceVersions',{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id']})['data']
|
477
|
+
default_version_value = payload['instance']['version'] ? payload['instance']['version'] : payload['version']
|
478
|
+
#default_layout_value = options[:layout]
|
479
|
+
if default_layout_value.nil?
|
480
|
+
default_layout_value = payload['instance']['layout'] ? payload['instance']['layout'] : payload['layout']
|
481
|
+
end
|
482
|
+
if default_layout_value && default_layout_value.is_a?(Hash)
|
483
|
+
default_layout_value = default_layout_value['id']
|
484
|
+
end
|
485
|
+
# JD: version is always nil because it is not stored in the blueprint or config !!
|
486
|
+
# so for now, infer the version from the layout
|
487
|
+
# requires api 3.6.2 to get "layouts" from /options/versions
|
488
|
+
if default_layout_value && default_version_value.to_s.empty?
|
489
|
+
available_versions.each do |available_version|
|
490
|
+
if available_version["layouts"]
|
491
|
+
selected_layout = available_version["layouts"].find {|it| it["value"].to_s == default_layout_value.to_s || it["id"].to_s == default_layout_value.to_s || it["code"].to_s == default_layout_value.to_s }
|
492
|
+
if selected_layout
|
493
|
+
default_version_value = available_version["value"]
|
494
|
+
break
|
495
|
+
end
|
496
|
+
end
|
468
497
|
end
|
469
498
|
end
|
499
|
+
|
500
|
+
# do not require version if a layout is passed
|
501
|
+
version_value = default_version_value
|
502
|
+
version_is_required = default_layout_value.nil?
|
503
|
+
if default_layout_value.nil? && options[:options]["layout"].nil? && options[:always_prompt] != true
|
504
|
+
#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']})
|
505
|
+
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']})
|
506
|
+
version_value = version_prompt['version']
|
507
|
+
end
|
470
508
|
end
|
471
|
-
end
|
472
509
|
|
473
|
-
|
474
|
-
version_value = default_version_value
|
475
|
-
version_is_required = default_layout_value.nil?
|
476
|
-
if default_layout_value.nil? && options[:options]["layout"].nil? && options[:always_prompt] != true
|
477
|
-
#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']})
|
478
|
-
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']})
|
479
|
-
version_value = version_prompt['version']
|
510
|
+
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']
|
480
511
|
end
|
481
512
|
end
|
482
513
|
|
483
|
-
# JD: there is a bug here, the version needs to be passed perhaps? or the optionSource methods need updating...
|
484
|
-
# could just allow for now ...
|
485
|
-
# if options[:options]["layout"]
|
486
|
-
# layout_id = options[:options]["layout"]
|
487
|
-
# ...
|
488
|
-
# end
|
489
|
-
layout_id = options[:layout].to_i if options[:layout]
|
490
|
-
|
491
514
|
# determine layout and provision_type
|
492
|
-
# provision_type = (layout && provision_type ? provision_type : nil) || get_provision_type_for_zone_type(cloud['zoneType']['id'])
|
493
|
-
# need to GET layout and provision type by ID in order to get optionTypes, and other settings...
|
494
|
-
|
495
|
-
if !layout_id
|
496
|
-
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']
|
497
|
-
end
|
498
515
|
|
499
516
|
# layout = find_instance_type_layout_by_id(instance_type['id'], layout_id.to_i)
|
500
|
-
layout = (instance_type['instanceTypeLayouts'] || []).find {|it|
|
517
|
+
layout = (instance_type['instanceTypeLayouts'] || []).find {|it|
|
518
|
+
it['id'].to_s == layout_id.to_s || it['code'].to_s == layout_id.to_s || it['name'].to_s == layout_id.to_s
|
519
|
+
}
|
501
520
|
if !layout
|
502
521
|
print_red_alert "Layout not found by id #{layout_id}"
|
503
522
|
exit 1
|
504
523
|
end
|
505
|
-
|
524
|
+
layout_id = layout['id']
|
525
|
+
payload['instance']['layout'] = {'id' => layout['id'], 'code' => layout['code']}
|
506
526
|
|
507
527
|
# need to GET provision type for optionTypes, and other settings...
|
508
528
|
provision_type_code = layout['provisionTypeCode'] || layout['provisionType']['code']
|
@@ -518,37 +538,47 @@ module Morpheus::Cli::ProvisioningHelper
|
|
518
538
|
end
|
519
539
|
|
520
540
|
# prompt for service plan
|
541
|
+
plan_id = nil
|
542
|
+
service_plan = nil
|
521
543
|
service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, layoutId: layout['id'], siteId: group_id})
|
522
544
|
service_plans = service_plans_json["plans"]
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
default_plan = nil
|
528
|
-
if payload['plan']
|
529
|
-
default_plan = payload['plan']
|
530
|
-
elsif payload['instance'] && payload['instance']['plan']
|
531
|
-
default_plan = payload['instance']['plan']
|
545
|
+
if locked_fields.include?('plan.id')
|
546
|
+
plan_id = options[:options]['plan']['id'] rescue nil
|
547
|
+
if plan_id.nil?
|
548
|
+
plan_id = options[:options]['instance']['plan']['id'] rescue nil
|
532
549
|
end
|
550
|
+
service_plan = service_plans.find {|sp| sp['id'] == plan_id }
|
551
|
+
else
|
552
|
+
service_plan = service_plans.find {|sp| sp['id'] == options[:service_plan].to_i} if options[:service_plan]
|
533
553
|
|
534
|
-
if options[:default_plan] && service_plans_dropdown.find {|sp| [sp["name"], sp["value"].to_s, sp["code"]].include?(options[:default_plan].to_s)}
|
535
|
-
default_plan_value = options[:default_plan]
|
536
|
-
else
|
537
|
-
default_plan_value = options[:default_plan] || (default_plan.is_a?(Hash) ? default_plan['id'] : default_plan)
|
538
|
-
end
|
539
|
-
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])
|
540
|
-
plan_id = plan_prompt['servicePlan']
|
541
|
-
service_plan = service_plans.find {|sp| sp["id"] == plan_id.to_i }
|
542
554
|
if !service_plan
|
543
|
-
|
544
|
-
|
555
|
+
service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"], 'code' => sp['code']} } # already sorted
|
556
|
+
default_plan = nil
|
557
|
+
if payload['plan']
|
558
|
+
default_plan = payload['plan']
|
559
|
+
elsif payload['instance'] && payload['instance']['plan']
|
560
|
+
default_plan = payload['instance']['plan']
|
561
|
+
end
|
562
|
+
|
563
|
+
if options[:default_plan] && service_plans_dropdown.find {|sp| [sp["name"], sp["value"].to_s, sp["code"]].include?(options[:default_plan].to_s)}
|
564
|
+
default_plan_value = options[:default_plan]
|
565
|
+
else
|
566
|
+
default_plan_value = options[:default_plan] || (default_plan.is_a?(Hash) ? default_plan['id'] : default_plan)
|
567
|
+
end
|
568
|
+
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])
|
569
|
+
plan_id = plan_prompt['servicePlan']
|
570
|
+
service_plan = service_plans.find {|sp| sp["id"] == plan_id.to_i }
|
571
|
+
if !service_plan
|
572
|
+
print_red_alert "Plan not found by id #{plan_id}"
|
573
|
+
exit 1
|
574
|
+
end
|
545
575
|
end
|
576
|
+
#todo: consolidate these, instances api looks for instance.plan.id and apps looks for plan.id
|
577
|
+
payload['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
|
578
|
+
payload['instance']['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
|
546
579
|
end
|
547
|
-
#todo: consolidate these, instances api looks for instance.plan.id and apps looks for plan.id
|
548
|
-
payload['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
|
549
|
-
payload['instance']['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
|
550
580
|
|
551
|
-
# build option types
|
581
|
+
# build config option types
|
552
582
|
option_type_list = []
|
553
583
|
if !layout['optionTypes'].nil? && !layout['optionTypes'].empty?
|
554
584
|
option_type_list += layout['optionTypes']
|
@@ -559,42 +589,43 @@ module Morpheus::Cli::ProvisioningHelper
|
|
559
589
|
if !provision_type.nil? && !provision_type['optionTypes'].nil? && !provision_type['optionTypes'].empty?
|
560
590
|
option_type_list += provision_type['optionTypes']
|
561
591
|
end
|
562
|
-
if !payload['volumes'].empty?
|
563
|
-
option_type_list = reject_volume_option_types(option_type_list)
|
564
|
-
end
|
565
|
-
# remove networkId option if networks were configured above
|
566
|
-
if !payload['networkInterfaces'].empty?
|
567
|
-
option_type_list = reject_networking_option_types(option_type_list)
|
568
|
-
end
|
569
592
|
|
570
593
|
# prompt for resource pool
|
571
594
|
pool_id = nil
|
572
595
|
resource_pool = nil
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
if
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
+
if locked_fields.include?('config.resourcePoolId')
|
597
|
+
pool_id = payload['config']['resourcePoolId'] rescue nil
|
598
|
+
elsif locked_fields.include?('config.resourcePool')
|
599
|
+
pool_id = payload['config']['resourcePool'] rescue nil
|
600
|
+
elsif locked_fields.include?('config.azureResourceGroupId')
|
601
|
+
pool_id = payload['config']['azureResourceGroupId'] rescue nil
|
602
|
+
else
|
603
|
+
has_zone_pools = provision_type && provision_type["id"] && provision_type["hasZonePools"]
|
604
|
+
if has_zone_pools
|
605
|
+
# pluck out the resourcePoolId option type to prompt for
|
606
|
+
resource_pool_option_type = option_type_list.find {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
607
|
+
option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
608
|
+
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']
|
609
|
+
resource_pool = resource_pool_options.find {|opt| opt['id'] == options[:resource_pool].to_i} if options[:resource_pool]
|
610
|
+
|
611
|
+
if resource_pool
|
612
|
+
pool_id = resource_pool['id']
|
613
|
+
else
|
614
|
+
if options[:default_resource_pool]
|
615
|
+
default_resource_pool = resource_pool_options.find {|rp| rp['id'] == options[:default_resource_pool]}
|
616
|
+
end
|
617
|
+
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}
|
618
|
+
resource_pool_prompt = Morpheus::Cli::OptionTypes.prompt([resource_pool_option_type],options[:options],api_client,{})
|
619
|
+
resource_pool_prompt.deep_compact!
|
620
|
+
payload.deep_merge!(resource_pool_prompt)
|
621
|
+
resource_pool = Morpheus::Cli::OptionTypes.get_last_select()
|
622
|
+
if resource_pool_option_type['fieldContext'] && resource_pool_prompt[resource_pool_option_type['fieldContext']]
|
623
|
+
pool_id = resource_pool_prompt[resource_pool_option_type['fieldContext']][resource_pool_option_type['fieldName']]
|
624
|
+
elsif resource_pool_prompt[resource_pool_option_type['fieldName']]
|
625
|
+
pool_id = resource_pool_prompt[resource_pool_option_type['fieldName']]
|
626
|
+
end
|
627
|
+
resource_pool ||= resource_pool_options.find {|it| it['id'] == pool_id}
|
596
628
|
end
|
597
|
-
resource_pool ||= resource_pool_options.find {|it| it['id'] == pool_id}
|
598
629
|
end
|
599
630
|
end
|
600
631
|
|
@@ -652,43 +683,81 @@ module Morpheus::Cli::ProvisioningHelper
|
|
652
683
|
end
|
653
684
|
|
654
685
|
# prompt for volumes
|
655
|
-
|
656
|
-
|
657
|
-
|
686
|
+
if locked_fields.include?('volumes')
|
687
|
+
payload['volumes'] = options[:options]['volumes'] if options[:options]['volumes']
|
688
|
+
else
|
689
|
+
volumes = prompt_volumes(service_plan, options, api_client, {zoneId: cloud_id, layoutId: layout['id'], siteId: group_id})
|
690
|
+
if !volumes.empty?
|
691
|
+
payload['volumes'] = volumes
|
692
|
+
end
|
658
693
|
end
|
659
694
|
|
660
695
|
# prompt networks
|
661
|
-
if
|
662
|
-
#
|
663
|
-
|
664
|
-
|
665
|
-
if
|
666
|
-
|
696
|
+
if locked_fields.include?('networks')
|
697
|
+
# payload['networkInterfaces'] = options[:options]['networkInterfaces'] if options[:options]['networkInterfaces']
|
698
|
+
else
|
699
|
+
if provision_type && provision_type["hasNetworks"]
|
700
|
+
# prompt for network interfaces (if supported)
|
701
|
+
begin
|
702
|
+
network_interfaces = prompt_network_interfaces(cloud_id, provision_type["id"], pool_id, options)
|
703
|
+
if !network_interfaces.empty?
|
704
|
+
payload['networkInterfaces'] = network_interfaces
|
705
|
+
end
|
706
|
+
rescue RestClient::Exception => e
|
707
|
+
print yellow,"Unable to load network options. Proceeding...",reset,"\n"
|
708
|
+
print_rest_exception(e, options) if Morpheus::Logging.debug?
|
667
709
|
end
|
668
|
-
rescue RestClient::Exception => e
|
669
|
-
print yellow,"Unable to load network options. Proceeding...",reset,"\n"
|
670
|
-
print_rest_exception(e, options) if Morpheus::Logging.debug?
|
671
710
|
end
|
672
711
|
end
|
673
|
-
# end
|
674
712
|
|
675
713
|
# Security Groups
|
676
|
-
#
|
714
|
+
# look for securityGroups option type... this is old and goofy
|
677
715
|
sg_option_type = option_type_list.find {|opt| ((opt['code'] == 'provisionType.amazon.securityId') || (opt['name'] == 'securityId')) }
|
678
716
|
option_type_list = option_type_list.reject {|opt| ((opt['code'] == 'provisionType.amazon.securityId') || (opt['name'] == 'securityId')) }
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
717
|
+
if locked_fields.include?('securityGroups')
|
718
|
+
# payload['securityGroups'] = options[:options]['securityGroups'] if options[:options]['securityGroups']
|
719
|
+
else
|
720
|
+
# prompt for multiple security groups
|
721
|
+
# ok.. seed data has changed and serverTypes do not have this optionType anymore...
|
722
|
+
if sg_option_type.nil?
|
723
|
+
if provision_type && (provision_type["code"] == 'amazon')
|
724
|
+
sg_option_type = {'fieldContext' => 'config', 'fieldName' => 'securityId', 'type' => 'select', 'fieldLabel' => 'Security Group', 'optionSource' => 'amazonSecurityGroup', 'required' => true, 'description' => 'Select security group.', 'defaultValue' => options[:default_security_group]}
|
725
|
+
end
|
683
726
|
end
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
727
|
+
sg_api_params = {zoneId: cloud_id, poolId: pool_id}
|
728
|
+
has_security_groups = !!sg_option_type
|
729
|
+
available_security_groups = []
|
730
|
+
if sg_option_type && sg_option_type['type'] == 'select' && sg_option_type['optionSource']
|
731
|
+
sg_option_results = options_interface.options_for_source(sg_option_type['optionSource'], sg_api_params)
|
732
|
+
available_security_groups = sg_option_results['data'].collect do |it|
|
733
|
+
{"id" => it["value"] || it["id"], "name" => it["name"], "value" => it["value"] || it["id"]}
|
734
|
+
end
|
735
|
+
end
|
736
|
+
if options[:security_groups]
|
737
|
+
# work with id or names, API expects ids though.
|
738
|
+
payload['securityGroups'] = options[:security_groups].collect {|sg_id|
|
739
|
+
found_sg = available_security_groups.find {|it| sg_id && (sg_id.to_s == it['id'].to_s || sg_id.to_s == it['name'].to_s) }
|
740
|
+
if found_sg.nil?
|
741
|
+
print_red_alert "Security group not found by name or id '#{sg_id}'"
|
742
|
+
exit 1
|
743
|
+
end
|
744
|
+
{'id' => found_sg['id']}
|
745
|
+
}
|
746
|
+
|
747
|
+
elsif has_security_groups
|
748
|
+
do_prompt_sg = true
|
749
|
+
if options[:default_security_groups]
|
750
|
+
payload['securityGroups'] = options[:default_security_groups]
|
751
|
+
security_groups_value = options[:default_security_groups].collect {|sg| sg['id'] }.join(',') rescue options[:default_security_groups]
|
752
|
+
# do_prompt_sg = (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Modify security groups? (#{security_groups_value})", {:default => false}))
|
753
|
+
do_prompt_sg = (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Modify security groups?", {:default => false}))
|
754
|
+
end
|
755
|
+
if do_prompt_sg
|
756
|
+
security_groups_array = prompt_security_groups(sg_option_type, sg_api_params, options)
|
757
|
+
if !security_groups_array.empty?
|
758
|
+
payload['securityGroups'] = security_groups_array.collect {|sg_id| {'id' => sg_id} }
|
759
|
+
end
|
760
|
+
end
|
692
761
|
end
|
693
762
|
end
|
694
763
|
|
@@ -732,10 +801,35 @@ module Morpheus::Cli::ProvisioningHelper
|
|
732
801
|
payload['evars'] = evars
|
733
802
|
end
|
734
803
|
|
735
|
-
#
|
736
|
-
metadata
|
737
|
-
|
738
|
-
|
804
|
+
# metadata tags
|
805
|
+
if options[:options]['metadata'].is_a?(Array) && !options[:metadata]
|
806
|
+
options[:metadata] = options[:options]['metadata']
|
807
|
+
end
|
808
|
+
if options[:metadata]
|
809
|
+
if options[:metadata] == "[]" || options[:metadata] == "null"
|
810
|
+
payload['metadata'] = []
|
811
|
+
elsif options[:metadata].is_a?(Array)
|
812
|
+
payload['metadata'] = options[:metadata]
|
813
|
+
else
|
814
|
+
# parse string into format name:value, name:value
|
815
|
+
# merge IDs from current metadata
|
816
|
+
# todo: should allow quoted semicolons..
|
817
|
+
metadata_list = options[:metadata].split(",").select {|it| !it.to_s.empty? }
|
818
|
+
metadata_list = metadata_list.collect do |it|
|
819
|
+
metadata_pair = it.split(":")
|
820
|
+
row = {}
|
821
|
+
row['name'] = metadata_pair[0].to_s.strip
|
822
|
+
row['value'] = metadata_pair[1].to_s.strip
|
823
|
+
row
|
824
|
+
end
|
825
|
+
payload['metadata'] = metadata_list
|
826
|
+
end
|
827
|
+
else
|
828
|
+
# prompt for metadata tags
|
829
|
+
metadata = prompt_metadata(options)
|
830
|
+
if !metadata.empty?
|
831
|
+
payload['metadata'] = metadata
|
832
|
+
end
|
739
833
|
end
|
740
834
|
|
741
835
|
return payload
|
@@ -1293,6 +1387,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
1293
1387
|
# end
|
1294
1388
|
# end
|
1295
1389
|
|
1390
|
+
# networkInterfaces may be passed as objects from blueprints or via -O networkInterfaces='[]'
|
1296
1391
|
field_context = interface_index == 0 ? "networkInterface" : "networkInterface#{interface_index+1}"
|
1297
1392
|
network_interface = {}
|
1298
1393
|
if options[:options] && options[:options]['networkInterfaces'] && options[:options]['networkInterfaces'][interface_index]
|
@@ -1300,14 +1395,20 @@ module Morpheus::Cli::ProvisioningHelper
|
|
1300
1395
|
end
|
1301
1396
|
|
1302
1397
|
default_network_id = network_interface['networkId'] || network_interface['id']
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1398
|
+
if default_network_id.nil? && network_interface['network'].is_a?(Hash) && network_interface['network']['id']
|
1399
|
+
default_network_id = network_interface['network']['id']
|
1400
|
+
end
|
1401
|
+
# JD: this for cluster or server prompting perhaps?
|
1402
|
+
# because zoneNetworkOptions already returns foramt like "id": "network-1"
|
1403
|
+
if !default_network_id || !default_network_id.to_s.include?("-")
|
1404
|
+
if network_interface['network'] && network_interface['network']['id']
|
1405
|
+
if network_interface['network']['subnet']
|
1406
|
+
default_network_id = "subnet-#{network_interface['network']['subnet']}"
|
1407
|
+
elsif network_interface['network']['group']
|
1408
|
+
default_network_id = "networkGroup-#{network_interface['network']['group']}"
|
1409
|
+
else
|
1410
|
+
default_network_id = "network-#{network_interface['network']['id']}"
|
1411
|
+
end
|
1311
1412
|
end
|
1312
1413
|
end
|
1313
1414
|
|
@@ -1318,7 +1419,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
1318
1419
|
network_interface['network'] = {}
|
1319
1420
|
network_interface['network']['id'] = v_prompt[field_context]['networkId'].to_s
|
1320
1421
|
selected_network = networks.find {|it| it["id"].to_s == network_interface['network']['id'] }
|
1321
|
-
network_options.reject! {|it| it['value'] == v_prompt[field_context]['networkId']}
|
1422
|
+
#network_options.reject! {|it| it['value'] == v_prompt[field_context]['networkId']}
|
1322
1423
|
|
1323
1424
|
if !selected_network
|
1324
1425
|
print_red_alert "Network not found by id #{network_interface['network']['id']}!"
|
@@ -1332,10 +1433,13 @@ module Morpheus::Cli::ProvisioningHelper
|
|
1332
1433
|
network_interface['networkInterfaceTypeId'] = v_prompt[field_context]['networkInterfaceTypeId'].to_i
|
1333
1434
|
end
|
1334
1435
|
|
1335
|
-
# choose IP
|
1436
|
+
# choose IP if network allows it
|
1437
|
+
# allowStaticOverride is only returned in 4.2.1+, so treat null as true for now..
|
1438
|
+
ip_available = selected_network['allowStaticOverride'] == true || selected_network['allowStaticOverride'].nil?
|
1336
1439
|
ip_required = true
|
1337
1440
|
if selected_network['id'].to_s.include?('networkGroup')
|
1338
1441
|
#puts "IP Address: Using network group." if !no_prompt
|
1442
|
+
ip_available = false
|
1339
1443
|
ip_required = false
|
1340
1444
|
elsif selected_network['pool']
|
1341
1445
|
#puts "IP Address: Using pool '#{selected_network['pool']['name']}'" if !no_prompt
|
@@ -1344,9 +1448,12 @@ module Morpheus::Cli::ProvisioningHelper
|
|
1344
1448
|
#puts "IP Address: Using DHCP" if !no_prompt
|
1345
1449
|
ip_required = false
|
1346
1450
|
end
|
1347
|
-
|
1348
|
-
if
|
1349
|
-
|
1451
|
+
|
1452
|
+
if ip_available
|
1453
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'ipAddress', 'type' => 'text', 'fieldLabel' => "IP Address", 'required' => ip_required, 'description' => 'Enter an IP for this network interface. x.x.x.x', 'defaultValue' => network_interface['ipAddress']}], options[:options])
|
1454
|
+
if v_prompt[field_context] && !v_prompt[field_context]['ipAddress'].to_s.empty?
|
1455
|
+
network_interface['ipAddress'] = v_prompt[field_context]['ipAddress']
|
1456
|
+
end
|
1350
1457
|
end
|
1351
1458
|
|
1352
1459
|
network_interfaces << network_interface
|
@@ -1493,27 +1600,6 @@ module Morpheus::Cli::ProvisioningHelper
|
|
1493
1600
|
return payload
|
1494
1601
|
end
|
1495
1602
|
|
1496
|
-
# reject old volume option types
|
1497
|
-
# these will eventually get removed from the associated optionTypes
|
1498
|
-
def reject_volume_option_types(option_types)
|
1499
|
-
option_types.reject {|opt|
|
1500
|
-
['osDiskSize', 'osDiskType',
|
1501
|
-
'diskSize', 'diskType',
|
1502
|
-
'datastoreId', 'storagePodId'
|
1503
|
-
].include?(opt['fieldName'])
|
1504
|
-
}
|
1505
|
-
end
|
1506
|
-
|
1507
|
-
# reject old networking option types
|
1508
|
-
# these will eventually get removed from the associated optionTypes
|
1509
|
-
def reject_networking_option_types(option_types)
|
1510
|
-
option_types.reject {|opt|
|
1511
|
-
['networkId', 'networkType', 'ipAddress', 'netmask', 'gateway', 'nameservers',
|
1512
|
-
'vmwareNetworkType', 'vmwareIpAddress', 'vmwareNetmask', 'vmwareGateway', 'vmwareNameservers',
|
1513
|
-
'subnetId'
|
1514
|
-
].include?(opt['fieldName'])
|
1515
|
-
}
|
1516
|
-
end
|
1517
1603
|
|
1518
1604
|
# reject old option types that now come from the selected service plan
|
1519
1605
|
# these will eventually get removed from the associated optionTypes
|