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
@@ -17,7 +17,8 @@ class Morpheus::Cli::Instances
17
17
  :logs, :stats, :stop, :start, :restart, :actions, :action, :suspend, :eject, :stop_service, :start_service, :restart_service,
18
18
  :backup, :backups, :resize, :clone, :envs, :setenv, :delenv,
19
19
  :lock, :unlock, :clone_image,
20
- :security_groups, :apply_security_groups, :run_workflow, :import_snapshot, :snapshot, :snapshots,
20
+ :security_groups, :apply_security_groups, :run_workflow,
21
+ :import_snapshot, :snapshot, :snapshots, :revert_to_snapshot, :remove_all_snapshots, :remove_all_container_snapshots, :create_linked_clone,
21
22
  :console, :status_check, {:containers => :list_containers},
22
23
  :scaling, {:'scaling-update' => :scaling_update},
23
24
  :wiki, :update_wiki,
@@ -52,6 +53,7 @@ class Morpheus::Cli::Instances
52
53
  @execution_request_interface = @api_client.execution_request
53
54
  @deploy_interface = @api_client.deploy
54
55
  @deployments_interface = @api_client.deployments
56
+ @snapshots_interface = @api_client.snapshots
55
57
  end
56
58
 
57
59
  def handle(args)
@@ -2718,6 +2720,12 @@ class Morpheus::Cli::Instances
2718
2720
  payload["volumes"] = volumes
2719
2721
  end
2720
2722
 
2723
+ # plan customizations
2724
+ plan_opts = prompt_service_plan_options(service_plan, options, @api_client, {}, instance)
2725
+ if plan_opts && !plan_opts.empty?
2726
+ payload['servicePlanOptions'] = plan_opts
2727
+ end
2728
+
2721
2729
  # only amazon supports this option
2722
2730
  # for now, always do this
2723
2731
  payload["deleteOriginalVolumes"] = true
@@ -3361,6 +3369,223 @@ EOT
3361
3369
  end
3362
3370
  end
3363
3371
 
3372
+ def revert_to_snapshot(args)
3373
+ options = {}
3374
+ instance = nil
3375
+ snapshot_id = nil
3376
+
3377
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
3378
+ opts.banner = subcommand_usage("[instance]")
3379
+ opts.on("--snapshot ID", String, "Optional snapshot") do |val|
3380
+ snapshot_id = val
3381
+ end
3382
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
3383
+ build_standard_add_options(opts, options) #, [:options, :payload, :json, :dry_run, :remote, :quiet])
3384
+ opts.footer = "Revert an Instance to saved Snapshot previously made." + "\n" +
3385
+ "[snapshotId] is required. This is the id of the snapshot to replace the current instance."
3386
+ end
3387
+
3388
+ optparse.parse!(args)
3389
+ if args.count != 1
3390
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
3391
+ end
3392
+ connect(options)
3393
+ begin
3394
+ instance = find_instance_by_name_or_id(args[0])
3395
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to revert instance '#{instance['name']}'?", options)
3396
+ exit 1
3397
+ end
3398
+ options[:options]['instanceId'] = instance['id']
3399
+ begin
3400
+ snapshot_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'snapshotId', 'type' => 'select', 'fieldLabel' => 'Snapshot', 'optionSource' => 'instanceSnapshots', 'required' => true, 'description' => 'Select Snapshot.'}], {}, @api_client, options[:options])
3401
+
3402
+ if !snapshot_prompt['snapshotId'].to_s.empty?
3403
+ snapshot_id = snapshot_prompt['snapshotId']
3404
+ end
3405
+ rescue RestClient::Exception => e
3406
+ puts "Failed to load instance snapshots"
3407
+ end
3408
+
3409
+ @instances_interface.setopts(options)
3410
+
3411
+ payload = {}
3412
+ if options[:dry_run]
3413
+ print_dry_run @instances_interface.dry.revert_to_snapshot(instance['id'], snapshot_id, payload)
3414
+ return
3415
+ end
3416
+
3417
+ json_response = @instances_interface.revert_to_snapshot(instance['id'], snapshot_id, payload)
3418
+ if options[:json]
3419
+ puts as_json(json_response, options)
3420
+ else
3421
+ print_green_success "Snapshot revert initiated."
3422
+ end
3423
+ return 0
3424
+
3425
+ rescue RestClient::Exception => e
3426
+ print_rest_exception(e, options)
3427
+ exit 1
3428
+ end
3429
+ end
3430
+
3431
+ def remove_all_container_snapshots(args)
3432
+ options = {}
3433
+ instance = nil
3434
+ container_id = nil
3435
+
3436
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
3437
+ opts.banner = subcommand_usage("[instance]")
3438
+ opts.on("--container ID", String, "Required container") do |val|
3439
+ container_id = val
3440
+ end
3441
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
3442
+ opts.footer = "Remove all snapshots attached to an instances container." + "\n" +
3443
+ "[containerId] is required. This is the id of the container which removes all attached snapshots."
3444
+ end
3445
+
3446
+ optparse.parse!(args)
3447
+ if args.count != 1
3448
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
3449
+ end
3450
+ connect(options)
3451
+ begin
3452
+ instance = find_instance_by_name_or_id(args[0])
3453
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove all snapshots for a container?", options)
3454
+ exit 1
3455
+ end
3456
+ options[:options]['instanceId'] = instance['id']
3457
+ begin
3458
+ container_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'containerId', 'type' => 'select', 'fieldLabel' => 'Container', 'optionSource' => 'instanceContainers', 'required' => true, 'description' => 'Select Container.'}], {}, @api_client, options[:options])
3459
+
3460
+ if !container_prompt['containerId'].to_s.empty?
3461
+ container_id = container_prompt['containerId']
3462
+ end
3463
+ rescue RestClient::Exception => e
3464
+ puts "Failed to load instance containers"
3465
+ end
3466
+
3467
+ @instances_interface.setopts(options)
3468
+
3469
+ payload = {}
3470
+ if options[:dry_run]
3471
+ print_dry_run @instances_interface.dry.remove_all_container_snapshots(instance['id'], container_id, payload)
3472
+ return
3473
+ end
3474
+
3475
+ json_response = @instances_interface.remove_all_container_snapshots(instance['id'], container_id, payload)
3476
+ if options[:json]
3477
+ puts as_json(json_response, options)
3478
+ else
3479
+ print_green_success "Snapshot delete initiated."
3480
+ end
3481
+ return 0
3482
+
3483
+ rescue RestClient::Exception => e
3484
+ print_rest_exception(e, options)
3485
+ exit 1
3486
+ end
3487
+ end
3488
+
3489
+ def remove_all_snapshots(args)
3490
+ options = {}
3491
+ instance = nil
3492
+
3493
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
3494
+ opts.banner = subcommand_usage("[instance]")
3495
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
3496
+ opts.footer = "Remove all snapshots attached to an instance." + "\n" +
3497
+ "Warning: This will remove all snapshots across all containers of an instance."
3498
+ end
3499
+
3500
+ optparse.parse!(args)
3501
+ if args.count != 1
3502
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
3503
+ end
3504
+ connect(options)
3505
+ begin
3506
+ instance = find_instance_by_name_or_id(args[0])
3507
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove all snapshots for this instance?", options)
3508
+ exit 1
3509
+ end
3510
+ options[:options]['instanceId'] = instance['id']
3511
+
3512
+ @instances_interface.setopts(options)
3513
+
3514
+ payload = {}
3515
+ if options[:dry_run]
3516
+ print_dry_run @instances_interface.dry.remove_all_instance_snapshots(instance['id'], payload)
3517
+ return
3518
+ end
3519
+
3520
+ json_response = @instances_interface.remove_all_instance_snapshots(instance['id'], payload)
3521
+ if options[:json]
3522
+ puts as_json(json_response, options)
3523
+ else
3524
+ print_green_success "Snapshots attaced to instance #{instance['name']} queued for deletion."
3525
+ end
3526
+ return 0
3527
+
3528
+ rescue RestClient::Exception => e
3529
+ print_rest_exception(e, options)
3530
+ exit 1
3531
+ end
3532
+ end
3533
+
3534
+ def create_linked_clone(args)
3535
+ options = {}
3536
+ instance = nil
3537
+ snapshot_id = nil
3538
+
3539
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
3540
+ opts.banner = subcommand_usage("[instance]")
3541
+ opts.on("--snapshot ID", String, "Optional snapshot") do |val|
3542
+ snapshot_id = val
3543
+ end
3544
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
3545
+ opts.footer = "Create a linked clone using the selected snapshot of an Instance." + "\n" +
3546
+ "[snapshotId] is required. This is the id of the snapshot which the clone will refer to."
3547
+ end
3548
+
3549
+ optparse.parse!(args)
3550
+ if args.count != 1
3551
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
3552
+ end
3553
+ connect(options)
3554
+ begin
3555
+ instance = find_instance_by_name_or_id(args[0])
3556
+ options[:options]['instanceId'] = instance['id']
3557
+ begin
3558
+ snapshot_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'snapshotId', 'type' => 'select', 'fieldLabel' => 'Snapshot', 'optionSource' => 'instanceSnapshots', 'required' => true, 'description' => 'Select Snapshot.'}], {}, @api_client, options[:options])
3559
+
3560
+ if !snapshot_prompt['snapshotId'].to_s.empty?
3561
+ snapshot_id = snapshot_prompt['snapshotId']
3562
+ end
3563
+ rescue RestClient::Exception => e
3564
+ puts "Failed to load instance snapshots"
3565
+ end
3566
+
3567
+ @instances_interface.setopts(options)
3568
+
3569
+ payload = {}
3570
+ if options[:dry_run]
3571
+ print_dry_run @instances_interface.dry.create_linked_clone(instance['id'], snapshot_id, payload)
3572
+ return
3573
+ end
3574
+
3575
+ json_response = @instances_interface.create_linked_clone(instance['id'], snapshot_id, payload)
3576
+ if options[:json]
3577
+ puts as_json(json_response, options)
3578
+ else
3579
+ print_green_success "Linked Clone creation initiated."
3580
+ end
3581
+ return 0
3582
+
3583
+ rescue RestClient::Exception => e
3584
+ print_rest_exception(e, options)
3585
+ exit 1
3586
+ end
3587
+ end
3588
+
3364
3589
 
3365
3590
  def scaling(args)
3366
3591
  options = {}
@@ -4133,6 +4358,9 @@ EOT
4133
4358
  opts.on( '--name VALUE', String, "Image Name (Template Name). Default is server name + timestamp" ) do |val|
4134
4359
  options[:options]['templateName'] = val
4135
4360
  end
4361
+ opts.on( '--folder VALUE', String, "Folder externalId or '/' to use the root folder" ) do |val|
4362
+ options[:options]['zoneFolder'] = val
4363
+ end
4136
4364
  build_standard_update_options(opts, options)
4137
4365
  opts.footer = <<-EOT
4138
4366
  Clone to image (template) for an instance
@@ -4144,6 +4372,18 @@ EOT
4144
4372
  connect(options)
4145
4373
  instance = find_instance_by_name_or_id(args[0])
4146
4374
  return 1 if instance.nil?
4375
+ # need to GET provision type for hasFolders
4376
+ provision_type_code = instance['layout']['provisionTypeCode'] rescue nil
4377
+ provision_type = nil
4378
+ if provision_type_code
4379
+ provision_type = provision_types_interface.list({code:provision_type_code})['provisionTypes'][0]
4380
+ if provision_type.nil?
4381
+ print_red_alert "Provision Type not found by code #{provision_type_code}"
4382
+ exit 1
4383
+ end
4384
+ else
4385
+ provision_type = get_provision_type_for_zone_type(cloud['zoneType']['id'])
4386
+ end
4147
4387
  payload = {}
4148
4388
  if options[:payload]
4149
4389
  payload = options[:payload]
@@ -4156,6 +4396,15 @@ EOT
4156
4396
  payload['templateName'] = v_prompt['templateName']
4157
4397
  end
4158
4398
  end
4399
+ #if instance['layout']['provisionTypeCode'] == 'vmware'
4400
+ if provision_type && provision_type["hasFolders"]
4401
+ if payload['zoneFolder'].nil?
4402
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneFolder', 'type' => 'select', 'optionSource' => 'vmwareFolders', 'fieldLabel' => 'Folder', 'description' => "Folder externalId or '/' to use the root folder", 'required' => true}], options[:options], @api_client, {siteId: instance['group']['id'], zoneId: instance['cloud']['id']})
4403
+ if v_prompt['zoneFolder'].to_s != ''
4404
+ payload['zoneFolder'] = v_prompt['zoneFolder']
4405
+ end
4406
+ end
4407
+ end
4159
4408
  end
4160
4409
  @instances_interface.setopts(options)
4161
4410
  if options[:dry_run]
@@ -39,6 +39,9 @@ class Morpheus::Cli::LibraryInstanceTypesCommand
39
39
  opts.on('--technology VALUE', String, "Filter by technology") do |val|
40
40
  params['provisionTypeCode'] = val
41
41
  end
42
+ opts.on('--featured [true|false]',String, "Filter by featured.") do |val|
43
+ params['featured'] = (val.to_s.downcase != 'false' && val.to_s.downcase != 'off')
44
+ end
42
45
  build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
43
46
  opts.footer = "List instance types."
44
47
  end
@@ -149,6 +149,11 @@ class Morpheus::Cli::NetworkStaticRoutesCommand
149
149
  return 1
150
150
  end
151
151
 
152
+ if !network_type['hasStaticRoutes']
153
+ print_red_alert "Static routes not supported for #{network_type['name']}"
154
+ return 1
155
+ end
156
+
152
157
  payload = nil
153
158
  if options[:payload]
154
159
  payload = options[:payload]
@@ -189,7 +189,7 @@ class Morpheus::Cli::NetworksCommand
189
189
  print cyan
190
190
  description_cols = {
191
191
  "ID" => 'id',
192
- "Name" => 'name',
192
+ "Name" => lambda {|it| it['displayName'] ? it['displayName'] : it['name'] },
193
193
  "Description" => 'description',
194
194
  "Type" => lambda {|it| it['type'] ? it['type']['name'] : '' },
195
195
  "Group" => lambda {|it| it['group'] ? it['group']['name'] : 'Shared' },
@@ -242,7 +242,7 @@ class Morpheus::Cli::NetworksCommand
242
242
  subnet_rows = subnets.collect { |subnet|
243
243
  {
244
244
  id: subnet['id'],
245
- name: " #{subnet['name']}",
245
+ name: " #{subnet['displayName'] || subnet['name']}",
246
246
  # type: subnet['type'] ? subnet['type']['name'] : '',
247
247
  type: "Subnet",
248
248
  cloud: network['zone'] ? network['zone']['name'] : '',
@@ -106,14 +106,12 @@ EOT
106
106
  if json_response['applianceUrl']
107
107
  appliance[:appliance_url] = json_response['applianceUrl']
108
108
  end
109
- # set status to ready if we have a version but no status yet for some reason
110
- if appliance[:build_version] && appliance[:status].nil?
111
- appliance[:status] = 'ready'
112
- end
113
- # update setupNeeded?
109
+ # setupNeeded?
114
110
  if json_response['setupNeeded'] == true
115
111
  # appliance[:setup_needed] = true
116
112
  appliance[:status] = 'fresh'
113
+ else
114
+ appliance[:status] = 'ready'
117
115
  end
118
116
  # if took_sec
119
117
  # appliance[:last_check] ||= {}
@@ -511,7 +511,7 @@ class Morpheus::Cli::PoliciesCommand
511
511
  policy_type_option_types = policy_type['optionTypes']
512
512
  # puts "POLICY OPTION TYPES:\n #{policy_type_option_types.inspect}"
513
513
  if policy_type_option_types
514
- config_prompt = Morpheus::Cli::OptionTypes.prompt(policy_type_option_types, options, @api_client)
514
+ config_prompt = Morpheus::Cli::OptionTypes.prompt(policy_type_option_types, options, @api_client, {}, false, true, true)
515
515
  # everything should be under fieldContext:'config'
516
516
  # payload['policy'].deep_merge!(config_prompt)
517
517
  if config_prompt['config']
@@ -69,6 +69,7 @@ class Morpheus::Cli::ProvisioningSettingsCommand
69
69
  "Hide Datastore Stats On Selection" => lambda {|it| format_boolean(it['hideDatastoreStats'])},
70
70
  "Cross-Tenant Naming Policies" => lambda {|it| format_boolean(it['crossTenantNamingPolicies'])},
71
71
  "Reuse Naming Sequence Numbers" => lambda {|it| format_boolean(it['reuseSequence'])},
72
+ "Show Console Keyboard Layout Settings" => lambda {|it| format_boolean(it['showConsoleKeyboardSettings'])},
72
73
  "Deployment Archive Store" => lambda {|it| it['deployStorageProvider'] ? it['deployStorageProvider']['name'] : nil},
73
74
  # Cloud-Init Settings
74
75
  "Cloud-Init Username" => lambda {|it| it['cloudInitUsername']},
@@ -102,7 +102,7 @@ EOT
102
102
  "URL" => lambda {|it| it[:url] || it[:host] },
103
103
  "Status" => lambda {|it| format_appliance_status(it, cyan) },
104
104
  "Version" => lambda {|it| it[:build_version] ? "#{it[:build_version]}" : '' },
105
- "Appliance URL" => lambda {|it| it[:appliance_url] ? "#{it[:appliance_url]}" : '' },
105
+ #"Appliance URL" => lambda {|it| it[:appliance_url] ? "#{it[:appliance_url]}" : '' },
106
106
  "Secure" => lambda {|it| format_boolean(it[:insecure] != true && (it[:url] || it[:host]).to_s.include?("https")) },
107
107
  "Active" => lambda {|it| it[:active] ? "Yes " + format_is_current() : "No" },
108
108
  #"Authenticated" => lambda {|it| format_boolean it[:authenticated] },
@@ -336,7 +336,7 @@ EOT
336
336
  print cyan,"Added remote #{new_appliance_name}, status is #{format_appliance_status(appliance)}",reset,"\n"
337
337
  end
338
338
 
339
- appliance, json_response = ::Morpheus::Cli::Remote.refresh_remote(new_appliance_name.to_sym)
339
+ #appliance, json_response = ::Morpheus::Cli::Remote.refresh_remote(new_appliance_name.to_sym)
340
340
  # if !options[:quiet]
341
341
  # print cyan
342
342
  # puts "Status: #{format_appliance_status(appliance)}"
@@ -390,7 +390,8 @@ EOT
390
390
  end
391
391
 
392
392
  end
393
-
393
+ # refresh to get buildVersion now that we are logged in
394
+ appliance, json_response = ::Morpheus::Cli::Remote.refresh_remote(new_appliance_name.to_sym)
394
395
  else
395
396
  #puts "Status is #{format_appliance_status(appliance)}"
396
397
  end
@@ -1278,7 +1279,7 @@ EOT
1278
1279
  "URL" => lambda {|it| it[:url] || it[:host] },
1279
1280
  #"Status" => lambda {|it| format_appliance_status(it, cyan) },
1280
1281
  "Version" => lambda {|it| it[:build_version] ? "#{it[:build_version]}" : '' },
1281
- "Appliance URL" => lambda {|it| it[:appliance_url] ? "#{it[:appliance_url]}" : '' },
1282
+ #"Appliance URL" => lambda {|it| it[:appliance_url] ? "#{it[:appliance_url]}" : '' },
1282
1283
  "Secure" => lambda {|it| format_appliance_secure(it) },
1283
1284
  "Active" => lambda {|it| it[:active] ? "Yes " + format_is_current() : "No" },
1284
1285
  # "Active" => lambda {|it| format_boolean(it[:active]) },
@@ -1696,7 +1697,10 @@ EOT
1696
1697
  # wtf, no url...
1697
1698
  return appliance, json_response
1698
1699
  else
1699
- setup_interface = Morpheus::SetupInterface.new({url:appliance_url, verify_ssl: !appliance[:insecure], timeout: timeout})
1700
+ # access token is needed for buildVersion
1701
+ wallet = Morpheus::Cli::Credentials.new(app_name, appliance_url).load_saved_credentials()
1702
+ setup_interface = Morpheus::SetupInterface.new({url:appliance_url, verify_ssl: !appliance[:insecure], timeout: timeout,
1703
+ access_token: (wallet && wallet['access_token']) ? wallet['access_token'] : nil})
1700
1704
  start_time = Time.now
1701
1705
  begin
1702
1706
  json_response = setup_interface.check(params)
@@ -1734,17 +1738,19 @@ EOT
1734
1738
  appliance[:last_check][:took] = (took_sec.to_f*1000).round
1735
1739
  end
1736
1740
  if json_response
1737
- if json_response.key?('applianceUrl')
1738
- appliance[:appliance_url] = json_response['applianceUrl']
1739
- end
1740
- if json_response.key?('buildVersion')
1741
- appliance[:build_version] = json_response['buildVersion']
1741
+ # if json_response.key?('applianceUrl')
1742
+ # appliance[:appliance_url] = json_response['applianceUrl']
1743
+ # end
1744
+ if json_response['success'] == true
1742
1745
  appliance[:status] = 'ready'
1743
1746
  appliance[:last_check][:success] = true
1744
1747
  # consider bumping this after every successful api command
1745
1748
  appliance[:last_success_at] = Time.now.to_i
1746
1749
  appliance.delete(:error)
1747
1750
  end
1751
+ if !json_response['buildVersion'].to_s.empty?
1752
+ appliance[:build_version] = json_response['buildVersion']
1753
+ end
1748
1754
  if json_response.key?('setupNeeded')
1749
1755
  if json_response['setupNeeded'] == true
1750
1756
  appliance[:setup_needed] = true
@@ -855,7 +855,7 @@ class Morpheus::Cli::SecurityGroups
855
855
 
856
856
  end
857
857
 
858
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'sourceType', 'fieldLabel' => 'Source Type', 'type' => 'select', 'optionSource' => 'securityGroupSourceType', 'required' => true, 'defaultValue' => 'cidr'}], options[:options], @api_client)
858
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'sourceType', 'fieldLabel' => 'Source Type', 'type' => 'select', 'optionSource' => 'securityGroupSourceType', 'required' => true, 'defaultValue' => 'cidr'}], options[:options], @api_client, {'rule.securityGroupId': security_group['id'], 'securityGroupRule.direction': payload['rule']['direction']})
859
859
  payload['rule']['sourceType'] = v_prompt['sourceType'] unless v_prompt['sourceType'].nil?
860
860
 
861
861
  if payload['rule']['sourceType'] == 'cidr'
@@ -869,7 +869,7 @@ class Morpheus::Cli::SecurityGroups
869
869
  payload['rule']['sourceTier'] = {"id" => v_prompt['sourceTier']} unless v_prompt['sourceTier'].nil?
870
870
  end
871
871
 
872
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destinationType', 'fieldLabel' => 'Destination Type', 'type' => 'select', 'optionSource' => 'securityGroupDestinationType', 'required' => true, 'defaultValue' => 'instance'}], options[:options], @api_client)
872
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destinationType', 'fieldLabel' => 'Destination Type', 'type' => 'select', 'optionSource' => 'securityGroupDestinationType', 'required' => true, 'defaultValue' => 'instance'}], options[:options], @api_client, {'rule.securityGroupId': security_group['id'], 'securityGroupRule.direction': payload['rule']['direction']})
873
873
  payload['rule']['destinationType'] = v_prompt['destinationType'] unless v_prompt['destinationType'].nil?
874
874
 
875
875
  if payload['rule']['destinationType'] == 'cidr'
@@ -575,7 +575,7 @@ class Morpheus::Cli::ServicePlanCommand
575
575
  options[:provisionType] = options[:provisionType] || (args.count > 1 ? args[1] : nil)
576
576
 
577
577
  if !options[:provisionType].nil?
578
- provision_types = @service_plans_interface.provision_types()['provisionTypes']
578
+ provision_types = @service_plans_interface.provision_types({max: 10000})['provisionTypes']
579
579
  provision_type = provision_types.find {|it| it['name'] == options[:provisionType] || it['code'] == options[:provisionType] || it['id'] == options[:provisionType].to_i}
580
580
 
581
581
  if provision_type.nil?
@@ -95,7 +95,7 @@ EOT
95
95
  # my_terminal.execute("setup needed?")
96
96
  # theres a bug here with --remote-url :status == "unknown"
97
97
  # but hey, we got json back, so set status to "ready"
98
- if appliance_status_json && appliance_status_json['setupNeeded'] == false
98
+ if appliance_status_json
99
99
  @remote_appliance[:status] == 'ready'
100
100
  end
101
101
  remote_status_string = format_appliance_status(@remote_appliance, cyan)
@@ -0,0 +1,139 @@
1
+ require 'morpheus/cli/cli_command'
2
+
3
+ class Morpheus::Cli::Snapshots
4
+ include Morpheus::Cli::CliCommand
5
+
6
+ set_command_name :snapshots
7
+ set_command_description "View or remove snapshot"
8
+ register_subcommands :get, :remove
9
+
10
+ alias_subcommand :details, :get
11
+ set_default_subcommand :get
12
+
13
+ def connect(opts)
14
+ @api_client = establish_remote_appliance_connection(opts)
15
+ @snapshots_interface = @api_client.snapshots
16
+ end
17
+
18
+ def handle(args)
19
+ handle_subcommand(args)
20
+ end
21
+
22
+ def get(args)
23
+ options = {}
24
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
25
+ opts.banner = subcommand_usage("[id]")
26
+ opts.footer = "Get Snapshot details." + "\n" +
27
+ "[snapshotId] is required. This is the id of the snapshot."
28
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
29
+ end
30
+ optparse.parse!(args)
31
+ if args.count < 1
32
+ puts_error "[id] argument is required"
33
+ puts_error optparse
34
+ return 1
35
+ end
36
+
37
+ connect(options)
38
+ id_list = parse_id_list(args)
39
+
40
+ return run_command_for_each_arg(id_list) do |arg|
41
+ _get(arg, options)
42
+ end
43
+ end
44
+
45
+ def _get(arg, options)
46
+ begin
47
+
48
+ @snapshots_interface.setopts(options)
49
+ if options[:dry_run]
50
+ print_dry_run @snapshots_interface.dry.get(arg.to_i)
51
+ return
52
+ end
53
+
54
+ json_response = @snapshots_interface.get(arg.to_i)
55
+ if options[:json]
56
+ puts as_json(json_response, options, "snapshot")
57
+ return 0
58
+ elsif options[:yaml]
59
+ puts as_yaml(json_response, options, "snapshot")
60
+ return 0
61
+ end
62
+
63
+ if options[:csv]
64
+ puts records_as_csv([json_response['snapshot']], options)
65
+ return 0
66
+ end
67
+ snapshot = json_response['snapshot']
68
+
69
+ print_h1 "Snapshot Details"
70
+ print cyan
71
+ description_cols = {
72
+ "ID" => 'id',
73
+ "Name" => 'name',
74
+ "Description" => 'description',
75
+ "External Id" => 'externalId',
76
+ "Status" => 'status',
77
+ "State" => 'state',
78
+ "Snapshot Type" => 'snapshotType',
79
+ "Snapshot Created" => 'snapshotCreated',
80
+ "Cloud" => 'zone.name',
81
+ "Datastore" => 'datastore',
82
+ "Parent Snapshot" => 'parentSnapshot',
83
+ "Active" => 'currentlyActive',
84
+ "Date Created" => 'dateCreated'
85
+ }
86
+ print_description_list(description_cols, snapshot)
87
+
88
+ print reset, "\n"
89
+
90
+ return 0
91
+ rescue RestClient::Exception => e
92
+ print_rest_exception(e, options)
93
+ return 1
94
+ end
95
+ end
96
+
97
+ def remove(args)
98
+ options = {}
99
+ instance = nil
100
+ snapshot_id = nil
101
+
102
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
103
+ opts.banner = subcommand_usage("[instance]")
104
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
105
+ opts.footer = "Remove/Delete a snapshot." + "\n" +
106
+ "[snapshotId] is required. This is the id of the snapshot to delete."
107
+ end
108
+
109
+ optparse.parse!(args)
110
+ if args.count != 1
111
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
112
+ end
113
+ snapshot_id = args[0].to_i
114
+ connect(options)
115
+ begin
116
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove a snapshot?", options)
117
+ exit 1
118
+ end
119
+
120
+ payload = {}
121
+ if options[:dry_run]
122
+ print_dry_run @snapshots_interface.dry.remove(snapshot_id, payload)
123
+ return
124
+ end
125
+
126
+ json_response = @snapshots_interface.remove(snapshot_id, payload)
127
+ if options[:json]
128
+ puts as_json(json_response, options)
129
+ else
130
+ print_green_success "Snapshot delete initiated."
131
+ end
132
+ return 0
133
+
134
+ rescue RestClient::Exception => e
135
+ print_rest_exception(e, options)
136
+ exit 1
137
+ end
138
+ end
139
+ end
@@ -179,7 +179,7 @@ class Morpheus::Cli::Tasks
179
179
  task_option_config = {}
180
180
  task_option_columns = []
181
181
  task_type['optionTypes'].sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i }.each do |optionType|
182
- if optionType['fieldLabel'].to_s.downcase == 'script'
182
+ if optionType['code'] == 'script'
183
183
  script_content = task['taskOptions'][optionType['fieldName']]
184
184
  elsif optionType['fieldName'] == 'httpHeaders' || optionType['fieldName'] == 'webHeaders'
185
185
  http_headers = task['taskOptions']['httpHeaders'] || task['taskOptions']['webHeaders']
@@ -553,11 +553,11 @@ class Morpheus::Cli::Tasks
553
553
  payload['task']['retryCount'] = v_prompt['retryCount'].to_i unless v_prompt['retryCount'].nil?
554
554
  end
555
555
  # Retry Delay
556
- if options[:options]['retryDelay']
557
- payload['task']['retryDelay'] = options[:options]['retryDelay'].to_i
556
+ if options[:options]['retryDelaySeconds']
557
+ payload['task']['retryDelaySeconds'] = options[:options]['retryDelaySeconds'].to_i
558
558
  else
559
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'retryDelay', 'fieldLabel' => 'Retry Delay', 'type' => 'number', 'defaultValue' => 10}], options[:options], @api_client)
560
- payload['task']['retryDelay'] = v_prompt['retryDelay'].to_i unless v_prompt['retryDelay'].nil?
559
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'retryDelaySeconds', 'fieldLabel' => 'Retry Delay', 'type' => 'number', 'defaultValue' => 10}], options[:options], @api_client)
560
+ payload['task']['retryDelaySeconds'] = v_prompt['retryDelaySeconds'].to_i unless v_prompt['retryDelaySeconds'].nil?
561
561
  end
562
562
  end
563
563