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.
- checksums.yaml +4 -4
- data/lib/morpheus/api/api_client.rb +4 -1
- data/lib/morpheus/api/catalog_item_types_interface.rb +20 -0
- data/lib/morpheus/api/instances_interface.rb +28 -0
- data/lib/morpheus/api/ping_interface.rb +2 -0
- data/lib/morpheus/api/setup_interface.rb +4 -0
- data/lib/morpheus/api/snapshots_interface.rb +19 -0
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +88 -0
- data/lib/morpheus/cli/commands/clusters.rb +59 -46
- data/lib/morpheus/cli/commands/hosts.rb +12 -0
- data/lib/morpheus/cli/commands/instances.rb +250 -1
- data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -0
- data/lib/morpheus/cli/commands/network_static_routes_command.rb +5 -0
- data/lib/morpheus/cli/commands/networks_command.rb +2 -2
- data/lib/morpheus/cli/commands/ping.rb +3 -5
- data/lib/morpheus/cli/commands/policies_command.rb +1 -1
- data/lib/morpheus/cli/commands/provisioning_settings_command.rb +1 -0
- data/lib/morpheus/cli/commands/remote.rb +16 -10
- data/lib/morpheus/cli/commands/security_groups.rb +2 -2
- data/lib/morpheus/cli/commands/service_plans_command.rb +1 -1
- data/lib/morpheus/cli/commands/setup.rb +1 -1
- data/lib/morpheus/cli/commands/snapshots.rb +139 -0
- data/lib/morpheus/cli/commands/tasks.rb +5 -5
- data/lib/morpheus/cli/commands/user_settings_command.rb +1 -1
- data/lib/morpheus/cli/commands/virtual_images.rb +4 -1
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +80 -0
- data/lib/morpheus/cli/option_types.rb +26 -11
- data/lib/morpheus/cli/version.rb +1 -1
- 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,
|
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
|
-
#
|
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
|
-
|
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
|
-
|
1739
|
-
end
|
1740
|
-
if json_response
|
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
|
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['
|
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]['
|
557
|
-
payload['task']['
|
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' => '
|
560
|
-
payload['task']['
|
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
|
|