morpheus-cli 5.4.2 → 5.4.3

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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/api_client.rb +4 -1
  3. data/lib/morpheus/api/catalog_item_types_interface.rb +20 -0
  4. data/lib/morpheus/api/instances_interface.rb +28 -0
  5. data/lib/morpheus/api/ping_interface.rb +2 -0
  6. data/lib/morpheus/api/setup_interface.rb +4 -0
  7. data/lib/morpheus/api/snapshots_interface.rb +19 -0
  8. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +88 -0
  9. data/lib/morpheus/cli/commands/clusters.rb +59 -46
  10. data/lib/morpheus/cli/commands/hosts.rb +12 -0
  11. data/lib/morpheus/cli/commands/instances.rb +250 -1
  12. data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -0
  13. data/lib/morpheus/cli/commands/network_static_routes_command.rb +5 -0
  14. data/lib/morpheus/cli/commands/networks_command.rb +2 -2
  15. data/lib/morpheus/cli/commands/ping.rb +3 -5
  16. data/lib/morpheus/cli/commands/policies_command.rb +1 -1
  17. data/lib/morpheus/cli/commands/provisioning_settings_command.rb +1 -0
  18. data/lib/morpheus/cli/commands/remote.rb +16 -10
  19. data/lib/morpheus/cli/commands/security_groups.rb +2 -2
  20. data/lib/morpheus/cli/commands/service_plans_command.rb +1 -1
  21. data/lib/morpheus/cli/commands/setup.rb +1 -1
  22. data/lib/morpheus/cli/commands/snapshots.rb +139 -0
  23. data/lib/morpheus/cli/commands/tasks.rb +5 -5
  24. data/lib/morpheus/cli/commands/user_settings_command.rb +1 -1
  25. data/lib/morpheus/cli/commands/virtual_images.rb +4 -1
  26. data/lib/morpheus/cli/mixins/provisioning_helper.rb +80 -0
  27. data/lib/morpheus/cli/option_types.rb +26 -11
  28. data/lib/morpheus/cli/version.rb +1 -1
  29. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d81fbae375d0d103b21c67cbbe12688b7d6977674b275047acf8e5dc9f2e155f
4
- data.tar.gz: f926189bc1792af28a86c1652a9b0b4268581d759fff857697e559e862aa09fb
3
+ metadata.gz: 1115efb46c7480c6a3814183c5748f27ce92d8be5ca935116fac0a26d66a58aa
4
+ data.tar.gz: a47a2aa8cb3d36dfff5de6e811c2948e54e54771d3e00c47ca377db50b77fbbf
5
5
  SHA512:
6
- metadata.gz: d5d832fc40ea3d0da75e4acfcd445fb59509b78fee5b87c81fa401237ed6ee8476a8a5de9fa11ce6bf2b1cac28f292bc0c6a5a9ef4345ca3c08a99baf084bee6
7
- data.tar.gz: 216b534d057fe67350a816ee00e45a4d9218f21a9a4ebeeadad764a9b12821720658bf56be6b873e63143c58be61064d20c88550cd4a4a88780748499fe2f386
6
+ metadata.gz: ab05b111e694eded06459369814d4dcf462766a48a861831a004e428324b7181b570b8df6b6c8097f5be6bc5fc3be2d2ea59ac44ae4003cc444b53e49d2a3665
7
+ data.tar.gz: b4760ef297c3a3dd9b19b71c0d4702885803dc5ae107a2cf538c074fd6a17191303910b28e119560113ce6f50208e250b6c07659e003da80c8c6c068cfad26ed
@@ -347,7 +347,6 @@ class Morpheus::APIClient
347
347
  end
348
348
 
349
349
  def auth
350
- # Morpheus::AuthInterface.new(common_interface_options).setopts(@options)
351
350
  Morpheus::AuthInterface.new({url: @base_url, client_id: @client_id, verify_ssl: @verify_ssl}).setopts(@options)
352
351
  end
353
352
 
@@ -889,6 +888,10 @@ class Morpheus::APIClient
889
888
  Morpheus::NetworkStaticRoutesInterface.new(common_interface_options).setopts(@options)
890
889
  end
891
890
 
891
+ def snapshots
892
+ Morpheus::SnapshotsInterface.new(common_interface_options).setopts(@options)
893
+ end
894
+
892
895
  def rest(endpoint)
893
896
  Morpheus::RestInterface.new(common_interface_options).setopts(@options.merge({base_path: "#{@base_url}/api/#{endpoint}"}))
894
897
  end
@@ -6,4 +6,24 @@ class Morpheus::CatalogItemTypesInterface < Morpheus::RestInterface
6
6
  "/api/catalog-item-types"
7
7
  end
8
8
 
9
+ # NOT json, multipart file upload
10
+ # def update_logo(id, logo_file)
11
+ # url = "#{base_path}/#{id}/update-logo"
12
+ # headers = { :params => {}, :authorization => "Bearer #{@access_token}"}
13
+ # payload = {}
14
+ # payload[:logo] = logo_file
15
+ # payload[:multipart] = true
16
+ # execute(method: :post, url: url, headers: headers, payload: payload)
17
+ # end
18
+
19
+ # NOT json, multipart file upload, uses PUT update endpoint
20
+ def update_logo(id, logo_file)
21
+ url = "#{base_path}/#{id}"
22
+ headers = { :params => {}, :authorization => "Bearer #{@access_token}"}
23
+ payload = {}
24
+ payload["catalogItemType"] = {"logo" => logo_file}
25
+ payload[:multipart] = true
26
+ execute(method: :put, url: url, headers: headers, payload: payload)
27
+ end
28
+
9
29
  end
@@ -262,6 +262,34 @@ class Morpheus::InstancesInterface < Morpheus::APIClient
262
262
  execute(opts)
263
263
  end
264
264
 
265
+ def revert_to_snapshot(id, snapshot_id, payload={})
266
+ url = "#{@base_url}/api/instances/#{id}/revert-snapshot/#{snapshot_id}"
267
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
268
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
269
+ execute(opts)
270
+ end
271
+
272
+ def remove_all_container_snapshots(id, container_id, payload={})
273
+ url = "#{@base_url}/api/instances/#{id}/delete-container-snapshots/#{container_id}"
274
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
275
+ opts = {method: :delete, url: url, headers: headers, payload: payload.to_json}
276
+ execute(opts)
277
+ end
278
+
279
+ def remove_all_instance_snapshots(id, payload={})
280
+ url = "#{@base_url}/api/instances/#{id}/delete-all-snapshots"
281
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
282
+ opts = {method: :delete, url: url, headers: headers, payload: payload.to_json}
283
+ execute(opts)
284
+ end
285
+
286
+ def create_linked_clone(id, snapshot_id, payload={})
287
+ url = "#{@base_url}/api/instances/#{id}/linked-clone/#{snapshot_id}"
288
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
289
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
290
+ execute(opts)
291
+ end
292
+
265
293
  def service_plans(params={})
266
294
  url = "#{@base_url}/api/instances/service-plans"
267
295
  headers = { params: params, authorization: "Bearer #{@access_token}" }
@@ -14,6 +14,8 @@ class Morpheus::PingInterface < Morpheus::APIClient
14
14
 
15
15
  def get(params={})
16
16
  headers = {params: params}
17
+ # use access token if authenticated
18
+ headers[:authorization] = "Bearer #{@access_token}" if @access_token
17
19
  execute(method: :get, url: "/api/ping", headers: headers)
18
20
  end
19
21
 
@@ -14,12 +14,16 @@ class Morpheus::SetupInterface < Morpheus::APIClient
14
14
 
15
15
  def get(params={})
16
16
  headers = {params: params}
17
+ # use access token if authenticated
18
+ headers[:authorization] = "Bearer #{@access_token}" if @access_token
17
19
  execute(method: :get, url: "/api/setup", headers: headers)
18
20
  end
19
21
 
20
22
  #this should go away and just use
21
23
  def check(params={}, timeout=5)
22
24
  headers = {params: params}
25
+ # use access token if authenticated
26
+ headers[:authorization] = "Bearer #{@access_token}" if @access_token
23
27
  execute(method: :get, url: "/api/setup/check", headers: headers, timeout: timeout)
24
28
  end
25
29
 
@@ -0,0 +1,19 @@
1
+ require 'morpheus/api/api_client'
2
+
3
+ # Snapshots API interface.
4
+ class Morpheus::SnapshotsInterface < Morpheus::APIClient
5
+
6
+ def get(snapshot_id)
7
+ url = "#{@base_url}/api/snapshots/#{snapshot_id}"
8
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
9
+ opts = {method: :get, url: url, headers: headers}
10
+ execute(opts)
11
+ end
12
+
13
+ def remove(snapshot_id, payload={})
14
+ url = "#{@base_url}/api/snapshots/#{snapshot_id}"
15
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
16
+ opts = {method: :delete, url: url, headers: headers, payload: payload.to_json}
17
+ execute(opts)
18
+ end
19
+ end
@@ -13,6 +13,7 @@ class Morpheus::Cli::CatalogItemTypesCommand
13
13
  set_command_description "Self Service: View and manage catalog item types"
14
14
 
15
15
  register_subcommands :list, :get, :add, :update, :remove
16
+ register_subcommands({:'update-logo' => :update_logo})
16
17
 
17
18
  def connect(opts)
18
19
  @api_client = establish_remote_appliance_connection(opts)
@@ -222,6 +223,7 @@ EOT
222
223
  def add(args)
223
224
  options = {}
224
225
  params = {}
226
+ logo_file = nil
225
227
  optparse = Morpheus::Cli::OptionParser.new do |opts|
226
228
  opts.banner = subcommand_usage("[name] [options]")
227
229
  # opts.on('-t', '--type [instance|blueprint|workflow]', "Item Type, default is instance.") do |val|
@@ -229,6 +231,19 @@ EOT
229
231
  # options[:options]['type'] = val.to_s.downcase
230
232
  # end
231
233
  build_option_type_options(opts, options, add_catalog_item_type_option_types)
234
+ opts.on('--logo FILE', String, "Upload a custom logo icon") do |val|
235
+ filename = val
236
+ logo_file = nil
237
+ if filename == 'null'
238
+ filename = 'null' # clear it
239
+ else
240
+ filename = File.expand_path(filename)
241
+ if !File.exists?(filename)
242
+ raise_command_error "File not found: #{filename}"
243
+ end
244
+ logo_file = File.new(filename, 'rb')
245
+ end
246
+ end
232
247
  opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
233
248
  options[:config_file] = val.to_s
234
249
  file_content = nil
@@ -330,6 +345,16 @@ EOT
330
345
  return 0, nil
331
346
  end
332
347
  json_response = @catalog_item_types_interface.create(payload)
348
+ if json_response['success']
349
+ if logo_file
350
+ begin
351
+ @catalog_item_types_interface.update_logo(json_response['catalogItemType']['id'], logo_file)
352
+ rescue RestClient::Exception => e
353
+ print_red_alert "Failed to save logo!"
354
+ print_rest_exception(e, options)
355
+ end
356
+ end
357
+ end
333
358
  catalog_item_type = json_response[catalog_item_type_object_key]
334
359
  render_response(json_response, options, catalog_item_type_object_key) do
335
360
  print_green_success "Added catalog item type #{catalog_item_type['name']}"
@@ -342,9 +367,23 @@ EOT
342
367
  options = {}
343
368
  params = {}
344
369
  payload = {}
370
+ logo_file = nil
345
371
  optparse = Morpheus::Cli::OptionParser.new do |opts|
346
372
  opts.banner = subcommand_usage("[type] [options]")
347
373
  build_option_type_options(opts, options, update_catalog_item_type_option_types)
374
+ opts.on('--logo FILE', String, "Upload a custom logo icon") do |val|
375
+ filename = val
376
+ logo_file = nil
377
+ if filename == 'null'
378
+ filename = 'null' # clear it
379
+ else
380
+ filename = File.expand_path(filename)
381
+ if !File.exists?(filename)
382
+ raise_command_error "File not found: #{filename}"
383
+ end
384
+ logo_file = File.new(filename, 'rb')
385
+ end
386
+ end
348
387
  opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
349
388
  options[:config_file] = val.to_s
350
389
  file_content = nil
@@ -445,6 +484,16 @@ EOT
445
484
  return
446
485
  end
447
486
  json_response = @catalog_item_types_interface.update(catalog_item_type['id'], payload)
487
+ if json_response['success']
488
+ if logo_file
489
+ begin
490
+ @catalog_item_types_interface.update_logo(json_response['catalogItemType']['id'], logo_file)
491
+ rescue RestClient::Exception => e
492
+ print_red_alert "Failed to save logo!"
493
+ print_rest_exception(e, options)
494
+ end
495
+ end
496
+ end
448
497
  catalog_item_type = json_response[catalog_item_type_object_key]
449
498
  render_response(json_response, options, catalog_item_type_object_key) do
450
499
  print_green_success "Updated catalog item type #{catalog_item_type['name']}"
@@ -453,6 +502,45 @@ EOT
453
502
  return 0, nil
454
503
  end
455
504
 
505
+ def update_logo(args)
506
+ options = {}
507
+ params = {}
508
+ filename = nil
509
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
510
+ opts.banner = subcommand_usage("[type] [file]")
511
+ build_common_options(opts, options, [:json, :dry_run, :remote])
512
+ opts.footer = "Update the logo for a catalog item type." + "\n" +
513
+ "[type] is required. This is the name or id of a catalog item type." + "\n" +
514
+ "[file] is required. This is the path of the logo file"
515
+ end
516
+ optparse.parse!(args)
517
+ verify_args!(args:args, optparse:optparse, count:2)
518
+ connect(options)
519
+ catalog_item_type = find_catalog_item_type_by_name_or_id(args[0])
520
+ return 1 if catalog_item_type.nil?
521
+ filename = args[1]
522
+ logo_file = nil
523
+ if filename == 'null'
524
+ filename = 'null' # clear it
525
+ else
526
+ filename = File.expand_path(filename)
527
+ if !File.exists?(filename)
528
+ raise_command_error "File not found: #{filename}"
529
+ end
530
+ logo_file = File.new(filename, 'rb')
531
+ end
532
+ @catalog_item_types_interface.setopts(options)
533
+ if options[:dry_run]
534
+ print_dry_run @catalog_item_types_interface.dry.update_logo(catalog_item_type['id'], logo_file)
535
+ return
536
+ end
537
+ json_response = @catalog_item_types_interface.update_logo(catalog_item_type['id'], logo_file)
538
+ render_response(json_response, options, catalog_item_type_object_key) do
539
+ print_green_success "Updated catalog item type #{catalog_item_type['name']} logo"
540
+ return _get(catalog_item_type["id"], {}, options)
541
+ end
542
+ end
543
+
456
544
  def remove(args)
457
545
  options = {}
458
546
  params = {}
@@ -547,11 +547,7 @@ class Morpheus::Cli::Clusters
547
547
  available_layouts = layouts_for_dropdown(cloud['id'], cluster_type['id'])
548
548
 
549
549
  if !available_layouts.empty?
550
- if available_layouts.count > 1 && !options[:no_prompt]
551
- layout_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'select', 'fieldLabel' => 'Layout', 'selectOptions' => available_layouts, 'required' => true, 'description' => 'Select Layout.'}],options[:options],@api_client,{})['layout']
552
- else
553
- layout_id = available_layouts.first['id']
554
- end
550
+ layout_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'select', 'fieldLabel' => 'Layout', 'selectOptions' => available_layouts, 'required' => true, 'description' => 'Select Layout.'}],options[:options],@api_client,{})['layout']
555
551
  layout = find_layout_by_name_or_id(layout_id)
556
552
  end
557
553
  end
@@ -560,17 +556,25 @@ class Morpheus::Cli::Clusters
560
556
 
561
557
  # Provision Type
562
558
  provision_type = (layout && layout['provisionType'] ? layout['provisionType'] : nil) || get_provision_type_for_zone_type(cloud['zoneType']['id'])
559
+ provision_type = @provision_types_interface.get(provision_type['id'])['provisionType'] if !provision_type.nil?
563
560
 
564
561
  api_params = {zoneId: cloud['id'], siteId: group['id'], layoutId: layout['id'], groupTypeId: cluster_type['id'], provisionType: provision_type['code'], provisionTypeId: provision_type['id']}
565
562
 
566
563
  # Controller type
567
- server_types = @server_types_interface.list({max:1, computeTypeId: cluster_type['controllerTypes'].first['id'], zoneTypeId: cloud['zoneType']['id'], useZoneProvisionTypes: true})['serverTypes']
564
+ server_types = @server_types_interface.list({computeTypeId: cluster_type['controllerTypes'].first['id'], zoneTypeId: cloud['zoneType']['id'], useZoneProvisionTypes: true})['serverTypes'].reject {|it| it['provisionType']['code'] == 'manual'}
568
565
  controller_provision_type = nil
569
566
  resource_pool = nil
570
567
 
571
568
  if !server_types.empty?
572
569
  controller_type = server_types.first
573
- controller_provision_type = controller_type['provisionType'] ? (@provision_types_interface.get(controller_type['provisionType']['id'])['provisionType'] rescue nil) : nil
570
+
571
+ if controller_type['provisionType']
572
+ if provision_type && provision_type['id'] == controller_type['provisionType']['id']
573
+ controller_provision_type = provision_type
574
+ else
575
+ controller_provision_type = @provision_types_interface.get(controller_type['provisionType']['id'])['provisionType'] rescue nil
576
+ end
577
+ end
574
578
 
575
579
  if controller_provision_type && resource_pool = prompt_resource_pool(group, cloud, nil, controller_provision_type, options)
576
580
  server_payload['config']['resourcePoolId'] = resource_pool['id']
@@ -585,21 +589,23 @@ class Morpheus::Cli::Clusters
585
589
  service_plan = prompt_service_plan(api_params, options)
586
590
 
587
591
  if service_plan
588
- server_payload['plan'] = {'id' => service_plan['id'], 'code' => service_plan['code'], 'options' => prompt_service_plan_options(service_plan, options)}
592
+ server_payload['plan'] = {'id' => service_plan['id'], 'code' => service_plan['code'], 'options' => prompt_service_plan_options(service_plan, provision_type, options)}
589
593
  api_params['planId'] = service_plan['id']
590
594
  end
591
595
 
592
596
  # Multi-disk / prompt for volumes
593
- volumes = options[:volumes] || prompt_volumes(service_plan, options.merge({'defaultAddFirstDataVolume': true}), @api_client, api_params)
594
-
595
- if !volumes.empty?
596
- server_payload['volumes'] = volumes
597
+ if provision_type['hasVolumes']
598
+ volumes = options[:volumes] || prompt_volumes(service_plan, options.merge({'defaultAddFirstDataVolume': true}), @api_client, api_params)
599
+ if !volumes.empty?
600
+ server_payload['volumes'] = volumes
601
+ end
597
602
  end
598
603
 
599
604
  # Options / Custom Config
600
605
  option_type_list =
601
- ((controller_type['optionTypes'].reject { |type| !type['enabled'] || type['fieldComponent'] } rescue []) + layout['optionTypes'] +
602
- (cluster_type['optionTypes'].reject { |type| !type['enabled'] || !type['creatable'] || type['fieldComponent'] } rescue [])).sort { |type| type['displayOrder'] }
606
+ ((controller_type.nil? ? [] : controller_type['optionTypes'].reject { |type| !type['enabled'] || type['fieldComponent'] } rescue []) +
607
+ layout['optionTypes'] +
608
+ (cluster_type['optionTypes'].reject { |type| !type['enabled'] || !type['creatable'] || type['fieldComponent'] } rescue []))
603
609
 
604
610
  # KLUDGE: google zone required for network selection
605
611
  if option_type = option_type_list.find {|type| type['code'] == 'computeServerType.googleLinux.googleZoneId'}
@@ -625,11 +631,13 @@ class Morpheus::Cli::Clusters
625
631
  cluster_payload.deep_merge!(Morpheus::Cli::OptionTypes.prompt(load_layout_options(cluster_payload), options[:options], @api_client, api_params, options[:no_prompt], true))
626
632
 
627
633
  # Server options
628
- server_payload.deep_merge!(Morpheus::Cli::OptionTypes.prompt(option_type_list, options[:options], @api_client, api_params, options[:no_prompt], true))
634
+ server_payload.deep_merge!(Morpheus::Cli::OptionTypes.prompt(option_type_list, options[:options].deep_merge({:context_map => {'domain' => ''}}), @api_client, api_params, options[:no_prompt], true))
629
635
 
630
636
  # Worker count
631
- default_node_count = layout['computeServers'] ? (layout['computeServers'].find {|it| it['nodeType'] == 'worker'} || {'nodeCount' => 3})['nodeCount'] : 3
632
- server_payload['config']['nodeCount'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => "config.nodeCount", 'type' => 'number', 'fieldLabel' => "#{['docker', 'kvm-cluster'].include?(cluster_type['code']) ? 'Host' : 'Worker'} Count", 'required' => true, 'defaultValue' => default_node_count > 0 ? default_node_count : 3}], options[:options], @api_client, api_params, options[:no_prompt])['config']['nodeCount']
637
+ if !['manual', 'external'].include?(provision_type['code'])
638
+ default_node_count = layout['computeServers'] ? (layout['computeServers'].find {|it| it['nodeType'] == 'worker'} || {'nodeCount' => 3})['nodeCount'] : 3
639
+ server_payload['config']['nodeCount'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => "config.nodeCount", 'type' => 'number', 'fieldLabel' => "#{['docker-cluster', 'kvm-cluster'].include?(cluster_type['code']) ? 'Host' : 'Worker'} Count", 'required' => true, 'defaultValue' => default_node_count > 0 ? default_node_count : 3}], options[:options], @api_client, api_params, options[:no_prompt])['config']['nodeCount']
640
+ end
633
641
 
634
642
  # Create User
635
643
  if !options[:createUser].nil?
@@ -657,10 +665,12 @@ class Morpheus::Cli::Clusters
657
665
  server_payload['hostname'] = options[:hostname] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'hostname', 'fieldLabel' => 'Hostname', 'type' => 'text', 'required' => true, 'description' => 'Hostname', 'defaultValue' => resourceName}], options[:options], @api_client, api_params)['hostname']
658
666
 
659
667
  # Workflow / Automation
660
- task_set_id = options[:taskSetId] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'taskSet', 'fieldLabel' => 'Workflow', 'type' => 'select', 'required' => false, 'optionSource' => 'taskSets'}], options[:options], @api_client, api_params.merge({'phase' => 'postProvision'}))['taskSet']
668
+ if provision_type['code'] != 'manual' && controller_type && controller_type['hasAutomation']
669
+ task_set_id = options[:taskSetId] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'taskSet', 'fieldLabel' => 'Workflow', 'type' => 'select', 'required' => false, 'optionSource' => 'taskSets'}], options[:options], @api_client, api_params.merge({'phase' => 'postProvision'}))['taskSet']
661
670
 
662
- if !task_set_id.nil?
663
- server_payload['taskSet'] = {'id' => task_set_id}
671
+ if !task_set_id.nil?
672
+ server_payload['taskSet'] = {'id' => task_set_id}
673
+ end
664
674
  end
665
675
 
666
676
  cluster_payload['server'] = server_payload
@@ -1172,7 +1182,7 @@ class Morpheus::Cli::Clusters
1172
1182
  service_plan = prompt_service_plan({zoneId: cloud_id, siteId: cluster['site']['id'], provisionTypeId: server_type['provisionType']['id'], groupTypeId: cluster_type['id'], }, options)
1173
1183
 
1174
1184
  if service_plan
1175
- server_payload['plan'] = {'code' => service_plan['code'], 'options' => prompt_service_plan_options(service_plan, options)}
1185
+ server_payload['plan'] = {'code' => service_plan['code'], 'options' => prompt_service_plan_options(service_plan, nil, options)}
1176
1186
  end
1177
1187
 
1178
1188
  if resource_pool = prompt_resource_pool(cluster, cloud, service_plan, server_type['provisionType'], options)
@@ -3713,34 +3723,37 @@ class Morpheus::Cli::Clusters
3713
3723
  service_plan
3714
3724
  end
3715
3725
 
3716
- def prompt_service_plan_options(service_plan, options)
3726
+ def prompt_service_plan_options(service_plan, provision_type, options)
3717
3727
  plan_options = {}
3718
-
3719
- # custom max memory
3720
- if service_plan['customMaxMemory']
3721
- if !options[:maxMemory]
3722
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'maxMemory', 'type' => 'number', 'fieldLabel' => 'Max Memory (MB)', 'required' => false, 'description' => 'This will override any memory requirement set on the virtual image', 'defaultValue' => service_plan['maxMemory'] ? service_plan['maxMemory'] / (1024 * 1024) : 10 }], options[:options])
3723
- plan_options['maxMemory'] = v_prompt['maxMemory'] * 1024 * 1024 if v_prompt['maxMemory']
3724
- else
3725
- plan_options['maxMemory'] = options[:maxMemory]
3728
+ hide_custom_options = provision_type && provision_type['code'] == 'manual'
3729
+
3730
+ if !hide_custom_options
3731
+ # custom max memory
3732
+ if service_plan['customMaxMemory']
3733
+ if !options[:maxMemory]
3734
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'maxMemory', 'type' => 'number', 'fieldLabel' => 'Max Memory (MB)', 'required' => false, 'description' => 'This will override any memory requirement set on the virtual image', 'defaultValue' => service_plan['maxMemory'] ? service_plan['maxMemory'] / (1024 * 1024) : 10 }], options[:options])
3735
+ plan_options['maxMemory'] = v_prompt['maxMemory'] * 1024 * 1024 if v_prompt['maxMemory']
3736
+ else
3737
+ plan_options['maxMemory'] = options[:maxMemory]
3738
+ end
3726
3739
  end
3727
- end
3728
3740
 
3729
- # custom cores: max cpu, max cores, cores per socket
3730
- if service_plan['customCores']
3731
- if options[:cpuCount].empty?
3732
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cpuCount', 'type' => 'number', 'fieldLabel' => 'CPU Count', 'required' => false, 'description' => 'Set CPU Count', 'defaultValue' => service_plan['maxCpu'] ? service_plan['maxCpu'] : 1 }], options[:options])
3733
- plan_options['cpuCount'] = v_prompt['cpuCount'] if v_prompt['cpuCount']
3734
- else
3735
- plan_options['cpuCount']
3736
- end
3737
- if options[:coreCount].empty?
3738
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'coreCount', 'type' => 'number', 'fieldLabel' => 'Core Count', 'required' => false, 'description' => 'Set Core Count', 'defaultValue' => service_plan['maxCores'] ? service_plan['maxCores'] : 1 }], options[:options])
3739
- plan_options['coreCount'] = v_prompt['coreCount'] if v_prompt['coreCount']
3740
- end
3741
- if options[:coresPerSocket].empty? && service_plan['coresPerSocket']
3742
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'coresPerSocket', 'type' => 'number', 'fieldLabel' => 'Cores Per Socket', 'required' => false, 'description' => 'Set Core Per Socket', 'defaultValue' => service_plan['coresPerSocket']}], options[:options])
3743
- plan_options['coresPerSocket'] = v_prompt['coresPerSocket'] if v_prompt['coresPerSocket']
3741
+ # custom cores: max cpu, max cores, cores per socket
3742
+ if service_plan['customCores']
3743
+ if options[:cpuCount].empty?
3744
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cpuCount', 'type' => 'number', 'fieldLabel' => 'CPU Count', 'required' => false, 'description' => 'Set CPU Count', 'defaultValue' => service_plan['maxCpu'] ? service_plan['maxCpu'] : 1 }], options[:options])
3745
+ plan_options['cpuCount'] = v_prompt['cpuCount'] if v_prompt['cpuCount']
3746
+ else
3747
+ plan_options['cpuCount']
3748
+ end
3749
+ if options[:coreCount].empty?
3750
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'coreCount', 'type' => 'number', 'fieldLabel' => 'Core Count', 'required' => false, 'description' => 'Set Core Count', 'defaultValue' => service_plan['maxCores'] ? service_plan['maxCores'] : 1 }], options[:options])
3751
+ plan_options['coreCount'] = v_prompt['coreCount'] if v_prompt['coreCount']
3752
+ end
3753
+ if options[:coresPerSocket].empty? && service_plan['coresPerSocket']
3754
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'coresPerSocket', 'type' => 'number', 'fieldLabel' => 'Cores Per Socket', 'required' => false, 'description' => 'Set Core Per Socket', 'defaultValue' => service_plan['coresPerSocket']}], options[:options])
3755
+ plan_options['coresPerSocket'] = v_prompt['coresPerSocket'] if v_prompt['coresPerSocket']
3756
+ end
3744
3757
  end
3745
3758
  end
3746
3759
  plan_options
@@ -878,6 +878,12 @@ class Morpheus::Cli::Hosts
878
878
  payload['volumes'] = volumes
879
879
  end
880
880
 
881
+ # plan customizations
882
+ plan_opts = prompt_service_plan_options(service_plan, options, @api_client, {})
883
+ if plan_opts && !plan_opts.empty?
884
+ payload['servicePlanOptions'] = plan_opts
885
+ end
886
+
881
887
  # prompt for network interfaces (if supported)
882
888
  if server_type["provisionType"] && server_type["provisionType"]["id"] && server_type["provisionType"]["hasNetworks"]
883
889
  begin
@@ -1252,6 +1258,12 @@ class Morpheus::Cli::Hosts
1252
1258
  payload[:volumes] = volumes
1253
1259
  end
1254
1260
 
1261
+ # plan customizations
1262
+ plan_opts = prompt_service_plan_options(service_plan, options, @api_client, {}, server)
1263
+ if plan_opts && !plan_opts.empty?
1264
+ payload['servicePlanOptions'] = plan_opts
1265
+ end
1266
+
1255
1267
  # todo: reconfigure networks
1256
1268
  # need to get provision_type_id for network info
1257
1269
  # prompt for network interfaces (if supported)