morpheus-cli 5.3.3 → 5.3.4
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 +12 -0
- data/lib/morpheus/api/clouds_interface.rb +4 -11
- data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
- data/lib/morpheus/api/load_balancer_profiles_interface.rb +10 -0
- data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +4 -4
- data/lib/morpheus/api/network_routers_interface.rb +21 -0
- data/lib/morpheus/api/network_servers_interface.rb +42 -0
- data/lib/morpheus/api/rest_interface.rb +2 -1
- data/lib/morpheus/api/virtual_servers_interface.rb +9 -0
- data/lib/morpheus/cli/cli_command.rb +2 -1
- data/lib/morpheus/cli/cloud_resource_pools_command.rb +1 -1
- data/lib/morpheus/cli/clouds.rb +22 -40
- data/lib/morpheus/cli/hosts.rb +0 -1
- data/lib/morpheus/cli/instances.rb +111 -7
- data/lib/morpheus/cli/invoices_command.rb +42 -38
- data/lib/morpheus/cli/library_option_lists_command.rb +3 -3
- data/lib/morpheus/cli/load_balancer_pools.rb +111 -0
- data/lib/morpheus/cli/load_balancer_virtual_servers.rb +136 -0
- data/lib/morpheus/cli/load_balancers.rb +0 -155
- data/lib/morpheus/cli/mixins/load_balancers_helper.rb +2 -2
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +32 -11
- data/lib/morpheus/cli/mixins/rest_command.rb +53 -37
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +488 -0
- data/lib/morpheus/cli/network_routers_command.rb +291 -7
- data/lib/morpheus/cli/network_scopes_command.rb +442 -0
- data/lib/morpheus/cli/networks_command.rb +2 -2
- data/lib/morpheus/cli/option_types.rb +20 -0
- data/lib/morpheus/cli/subnets_command.rb +7 -2
- data/lib/morpheus/cli/tasks.rb +25 -2
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +2 -0
- data/lib/morpheus/cli.rb +9 -1
- metadata +9 -2
@@ -306,20 +306,20 @@ class Morpheus::Cli::InvoicesCommand
|
|
306
306
|
|
307
307
|
if invoice_totals
|
308
308
|
cost_rows = [
|
309
|
-
{label: 'Price'.upcase, compute: invoice_totals['actualComputePrice'], memory: invoice_totals['actualMemoryPrice'], storage: invoice_totals['actualStoragePrice'], network: invoice_totals['actualNetworkPrice'], license: invoice_totals['actualLicensePrice'], extra: invoice_totals['actualExtraPrice'], running: invoice_totals['actualRunningPrice'], total: invoice_totals['actualTotalPrice'], currency:
|
309
|
+
{label: 'Price'.upcase, compute: invoice_totals['actualComputePrice'], memory: invoice_totals['actualMemoryPrice'], storage: invoice_totals['actualStoragePrice'], network: invoice_totals['actualNetworkPrice'], license: invoice_totals['actualLicensePrice'], extra: invoice_totals['actualExtraPrice'], running: invoice_totals['actualRunningPrice'], total: invoice_totals['actualTotalPrice'], currency: invoice_totals['actualCurrency']},
|
310
310
|
]
|
311
311
|
if options[:show_costs]
|
312
312
|
cost_rows += [
|
313
|
-
{label: 'Cost'.upcase, compute: invoice_totals['actualComputeCost'], memory: invoice_totals['actualMemoryCost'], storage: invoice_totals['actualStorageCost'], network: invoice_totals['actualNetworkCost'], license: invoice_totals['actualLicenseCost'], extra: invoice_totals['actualExtraCost'], running: invoice_totals['actualRunningCost'], total: invoice_totals['actualTotalCost'], currency:
|
313
|
+
{label: 'Cost'.upcase, compute: invoice_totals['actualComputeCost'], memory: invoice_totals['actualMemoryCost'], storage: invoice_totals['actualStorageCost'], network: invoice_totals['actualNetworkCost'], license: invoice_totals['actualLicenseCost'], extra: invoice_totals['actualExtraCost'], running: invoice_totals['actualRunningCost'], total: invoice_totals['actualTotalCost'], currency: invoice_totals['actualCurrency']}
|
314
314
|
]
|
315
315
|
end
|
316
316
|
if options[:show_estimates]
|
317
317
|
cost_rows += [
|
318
|
-
{label: 'Metered Price'.upcase, compute: invoice_totals['estimatedComputePrice'], memory: invoice_totals['estimatedMemoryPrice'], storage: invoice_totals['estimatedStoragePrice'], network: invoice_totals['estimatedNetworkPrice'], license: invoice_totals['estimatedLicensePrice'], extra: invoice_totals['estimatedExtraPrice'], running: invoice_totals['estimatedRunningPrice'], total: invoice_totals['estimatedTotalPrice'], currency:
|
318
|
+
{label: 'Metered Price'.upcase, compute: invoice_totals['estimatedComputePrice'], memory: invoice_totals['estimatedMemoryPrice'], storage: invoice_totals['estimatedStoragePrice'], network: invoice_totals['estimatedNetworkPrice'], license: invoice_totals['estimatedLicensePrice'], extra: invoice_totals['estimatedExtraPrice'], running: invoice_totals['estimatedRunningPrice'], total: invoice_totals['estimatedTotalPrice'], currency: invoice_totals['estimatedCurrency']}
|
319
319
|
]
|
320
320
|
if options[:show_costs]
|
321
321
|
cost_rows += [
|
322
|
-
{label: 'Metered Cost'.upcase, compute: invoice_totals['estimatedComputeCost'], memory: invoice_totals['estimatedMemoryCost'], storage: invoice_totals['estimatedStorageCost'], network: invoice_totals['estimatedNetworkCost'], license: invoice_totals['estimatedLicenseCost'], extra: invoice_totals['estimatedExtraCost'], running: invoice_totals['estimatedRunningCost'], total: invoice_totals['estimatedTotalCost'], currency:
|
322
|
+
{label: 'Metered Cost'.upcase, compute: invoice_totals['estimatedComputeCost'], memory: invoice_totals['estimatedMemoryCost'], storage: invoice_totals['estimatedStorageCost'], network: invoice_totals['estimatedNetworkCost'], license: invoice_totals['estimatedLicenseCost'], extra: invoice_totals['estimatedExtraCost'], running: invoice_totals['estimatedRunningCost'], total: invoice_totals['estimatedTotalCost'], currency: invoice_totals['estimatedCurrency']}
|
323
323
|
]
|
324
324
|
end
|
325
325
|
end
|
@@ -360,7 +360,7 @@ class Morpheus::Cli::InvoicesCommand
|
|
360
360
|
end
|
361
361
|
|
362
362
|
def get(args)
|
363
|
-
options = {}
|
363
|
+
options, params = {}, {}
|
364
364
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
365
365
|
opts.banner = subcommand_usage("[id]")
|
366
366
|
opts.on('-a', '--all', "Display all details, costs and prices." ) do
|
@@ -381,7 +381,6 @@ class Morpheus::Cli::InvoicesCommand
|
|
381
381
|
options[:sigdig] = val.to_i
|
382
382
|
end
|
383
383
|
build_standard_get_options(opts, options)
|
384
|
-
opts.footer = "Get details about a specific invoice."
|
385
384
|
opts.footer = <<-EOT
|
386
385
|
Get details about a specific invoice.
|
387
386
|
[id] is required. This is the id of an invoice.
|
@@ -390,32 +389,27 @@ EOT
|
|
390
389
|
optparse.parse!(args)
|
391
390
|
verify_args!(args:args, optparse:optparse, min:1)
|
392
391
|
connect(options)
|
392
|
+
params.merge!(parse_query_options(options))
|
393
393
|
id_list = parse_id_list(args)
|
394
394
|
return run_command_for_each_arg(id_list) do |arg|
|
395
|
-
_get(arg, options)
|
395
|
+
_get(arg, params, options)
|
396
396
|
end
|
397
397
|
end
|
398
398
|
|
399
|
-
def _get(id, options)
|
400
|
-
|
401
|
-
|
402
|
-
@invoices_interface.
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
json_response
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
end
|
412
|
-
render_result = render_with_format(json_response, options, 'invoice')
|
413
|
-
return 0 if render_result
|
414
|
-
|
399
|
+
def _get(id, params, options)
|
400
|
+
@invoices_interface.setopts(options)
|
401
|
+
if options[:dry_run]
|
402
|
+
print_dry_run @invoices_interface.dry.get(id, params)
|
403
|
+
return
|
404
|
+
end
|
405
|
+
json_response = @invoices_interface.get(id, params)
|
406
|
+
if options[:hide_line_items]
|
407
|
+
json_response['invoice'].delete('lineItems') rescue nil
|
408
|
+
end
|
409
|
+
render_response(json_response, options, invoice_object_key) do
|
410
|
+
invoice = json_response[invoice_object_key]
|
415
411
|
print_h1 "Invoice Details"
|
416
412
|
print cyan
|
417
|
-
|
418
|
-
|
419
413
|
description_cols = {
|
420
414
|
"Invoice ID" => lambda {|it| it['id'] },
|
421
415
|
"Type" => lambda {|it| format_invoice_ref_type(it) },
|
@@ -550,15 +544,9 @@ EOT
|
|
550
544
|
cost_columns.delete("Extra".upcase)
|
551
545
|
end
|
552
546
|
print as_pretty_table(cost_rows, cost_columns, options)
|
553
|
-
|
554
|
-
|
555
|
-
|
556
547
|
print reset,"\n"
|
557
|
-
return 0
|
558
|
-
rescue RestClient::Exception => e
|
559
|
-
print_rest_exception(e, options)
|
560
|
-
return 1
|
561
548
|
end
|
549
|
+
return 0, nil
|
562
550
|
end
|
563
551
|
|
564
552
|
def update(args)
|
@@ -618,7 +606,7 @@ Update an invoice.
|
|
618
606
|
invoice = json_response['invoice']
|
619
607
|
render_response(json_response, options, 'invoice') do
|
620
608
|
print_green_success "Updated invoice #{invoice['id']}"
|
621
|
-
return _get(invoice["id"], options)
|
609
|
+
return _get(invoice["id"], {}, options)
|
622
610
|
end
|
623
611
|
return 0, nil
|
624
612
|
end
|
@@ -927,14 +915,13 @@ EOT
|
|
927
915
|
end
|
928
916
|
|
929
917
|
def get_line_item(args)
|
930
|
-
options = {}
|
918
|
+
options, params = {}, {}
|
931
919
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
932
920
|
opts.banner = subcommand_usage("[id]")
|
933
921
|
opts.on('--sigdig DIGITS', "Significant digits when rounding cost values for display as currency. Default is 2. eg. $3.50") do |val|
|
934
922
|
options[:sigdig] = val.to_i
|
935
923
|
end
|
936
924
|
build_standard_get_options(opts, options)
|
937
|
-
opts.footer = "Get details about a specific invoice line item."
|
938
925
|
opts.footer = <<-EOT
|
939
926
|
Get details about a specific invoice line item.
|
940
927
|
[id] is required. This is the id of an invoice line item.
|
@@ -943,14 +930,15 @@ EOT
|
|
943
930
|
optparse.parse!(args)
|
944
931
|
verify_args!(args:args, optparse:optparse, min:1)
|
945
932
|
connect(options)
|
933
|
+
params.merge!(parse_query_options(options))
|
946
934
|
id_list = parse_id_list(args)
|
947
935
|
return run_command_for_each_arg(id_list) do |arg|
|
948
|
-
_get_line_item(arg, options)
|
936
|
+
_get_line_item(arg, params, options)
|
949
937
|
end
|
950
938
|
end
|
951
939
|
|
952
|
-
|
953
|
-
|
940
|
+
|
941
|
+
def _get_line_item(id, params, options)
|
954
942
|
@invoice_line_items_interface.setopts(options)
|
955
943
|
if options[:dry_run]
|
956
944
|
print_dry_run @invoice_line_items_interface.dry.get(id, params)
|
@@ -995,6 +983,22 @@ EOT
|
|
995
983
|
|
996
984
|
private
|
997
985
|
|
986
|
+
def invoice_object_key
|
987
|
+
'invoice'
|
988
|
+
end
|
989
|
+
|
990
|
+
def invoice_list_key
|
991
|
+
'invoices'
|
992
|
+
end
|
993
|
+
|
994
|
+
def invoice_line_item_object_key
|
995
|
+
'lineItem'
|
996
|
+
end
|
997
|
+
|
998
|
+
def invoice_line_item_list_key
|
999
|
+
'lineItems'
|
1000
|
+
end
|
1001
|
+
|
998
1002
|
# def find_invoice_by_name_or_id(val)
|
999
1003
|
# if val.to_s =~ /\A\d{1,}\Z/
|
1000
1004
|
# return find_invoice_by_id(val)
|
@@ -429,9 +429,9 @@ class Morpheus::Cli::LibraryOptionListsCommand
|
|
429
429
|
{'dependsOnCode' => 'optionTypeList.type:ldap', 'fieldName' => 'sourceUsername', 'fieldLabel' => 'Source Username', 'type' => 'text', 'description' => "An LDAP Username for use when type is 'ldap'.", 'displayOrder' => 10},
|
430
430
|
{'dependsOnCode' => 'optionTypeList.type:ldap', 'fieldName' => 'sourcePassword', 'fieldLabel' => 'Source Username', 'type' => 'text', 'description' => "An LDAP Password for use when type is 'ldap'.", 'displayOrder' => 11},
|
431
431
|
{'dependsOnCode' => 'optionTypeList.type:ldap', 'fieldName' => 'ldapQuery', 'fieldLabel' => 'LDAP Query', 'type' => 'text', 'description' => "LDAP Queries are standard LDAP formatted queries where different objects can be searched. Dependent parameters can be loaded into the query using the <%=phrase%> syntax.", 'displayOrder' => 12},
|
432
|
-
{'dependsOnCode' => 'optionTypeList.type:rest|api|manual', 'fieldName' => 'initialDataset', 'fieldLabel' => 'Initial Dataset', 'type' => 'code-editor', 'description' => "Create an initial json dataset to be used as the collection for this option list. It should be a list containing objects with properties 'name', and 'value'. However, if there is a translation script, that will also be passed through.", 'displayOrder' => 13},
|
433
|
-
{'dependsOnCode' => 'optionTypeList.type:rest|api|ldap', 'fieldName' => 'translationScript', 'fieldLabel' => 'Translation Script', 'type' => 'code-editor', 'description' => "Create a js script to translate the result data object into an Array containing objects with properties name, and value. The input data is provided as data and the result should be put on the global variable results.", 'displayOrder' => 14},
|
434
|
-
{'dependsOnCode' => 'optionTypeList.type:rest|api', 'fieldName' => 'requestScript', 'fieldLabel' => 'Request Script', 'type' => 'code-editor', 'description' => "Create a js script to prepare the request. Return a data object as the body for a post, and return an array containing properties name and value for a get. The input data is provided as data and the result should be put on the global variable results.", 'displayOrder' => 15},
|
432
|
+
{'dependsOnCode' => 'optionTypeList.type:rest|api|manual', 'fieldName' => 'initialDataset', 'fieldLabel' => 'Initial Dataset', 'type' => 'code-editor', 'description' => "Create an initial json dataset to be used as the collection for this option list. It should be a list containing objects with properties 'name', and 'value'. However, if there is a translation script, that will also be passed through.", 'displayOrder' => 13, 'dataType' => 'string'},
|
433
|
+
{'dependsOnCode' => 'optionTypeList.type:rest|api|ldap', 'fieldName' => 'translationScript', 'fieldLabel' => 'Translation Script', 'type' => 'code-editor', 'description' => "Create a js script to translate the result data object into an Array containing objects with properties name, and value. The input data is provided as data and the result should be put on the global variable results.", 'displayOrder' => 14, 'dataType' => 'string'},
|
434
|
+
{'dependsOnCode' => 'optionTypeList.type:rest|api', 'fieldName' => 'requestScript', 'fieldLabel' => 'Request Script', 'type' => 'code-editor', 'description' => "Create a js script to prepare the request. Return a data object as the body for a post, and return an array containing properties name and value for a get. The input data is provided as data and the result should be put on the global variable results.", 'displayOrder' => 15, 'dataType' => 'string'},
|
435
435
|
]
|
436
436
|
|
437
437
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
|
3
|
+
class Morpheus::Cli::LoadBalancerPools
|
4
|
+
include Morpheus::Cli::CliCommand
|
5
|
+
include Morpheus::Cli::RestCommand
|
6
|
+
include Morpheus::Cli::LoadBalancersHelper
|
7
|
+
|
8
|
+
set_command_hidden # hide until ready
|
9
|
+
set_command_name :'load-balancer-pools'
|
10
|
+
register_subcommands :list, :get, :add, :update, :remove
|
11
|
+
|
12
|
+
register_interfaces :load_balancer_pools,
|
13
|
+
:load_balancers, :load_balancer_pools
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def load_balancer_pool_list_column_definitions()
|
18
|
+
{
|
19
|
+
"ID" => 'id',
|
20
|
+
"Name" => 'name',
|
21
|
+
"Balancer Mode" => lambda {|it| it['vipBalance'] },
|
22
|
+
"LB" => lambda {|it| it['loadBalancer'] ? it['loadBalancer']['name'] : '' },
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def load_balancer_pool_column_definitions()
|
27
|
+
{
|
28
|
+
"ID" => 'id',
|
29
|
+
"Name" => 'name',
|
30
|
+
"Description" => 'description',
|
31
|
+
"Balancer Mode" => lambda {|it| it['vipBalance'] },
|
32
|
+
"LB" => lambda {|it| it['loadBalancer'] ? it['loadBalancer']['name'] : '' },
|
33
|
+
# todo: more properties to show here
|
34
|
+
"Status" => lambda {|it| format_load_balancer_pool_status(it) },
|
35
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
36
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_balancer_pool_object_key
|
41
|
+
'loadBalancerPool'
|
42
|
+
end
|
43
|
+
|
44
|
+
def load_balancer_pool_list_key
|
45
|
+
'loadBalancerPools'
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_balancer_pool_label
|
49
|
+
'Load Balancer Pool'
|
50
|
+
end
|
51
|
+
|
52
|
+
def load_balancer_pool_label_plural
|
53
|
+
'Load Balancer Pools'
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_load_balancer_pool_by_name_or_id(val)
|
57
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
58
|
+
return find_load_balancer_pool_by_id(val)
|
59
|
+
else
|
60
|
+
return find_load_balancer_pool_by_name(val)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def find_load_balancer_pool_by_id(id)
|
65
|
+
begin
|
66
|
+
json_response = load_balancer_pools_interface.get(id.to_i)
|
67
|
+
return json_response[load_balancer_pool_object_key]
|
68
|
+
rescue RestClient::Exception => e
|
69
|
+
if e.response && e.response.code == 404
|
70
|
+
print_red_alert "#{load_balancer_pool_label} not found by id #{id}"
|
71
|
+
return nil
|
72
|
+
else
|
73
|
+
raise e
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def find_load_balancer_pool_by_name(name)
|
79
|
+
json_response = load_balancer_pools_interface.list({name: name.to_s})
|
80
|
+
load_balancer_pools = json_response[load_balancer_pool_list_key]
|
81
|
+
if load_balancer_pools.empty?
|
82
|
+
print_red_alert "#{load_balancer_pool_label_plural} not found by name #{name}"
|
83
|
+
return load_balancer_pools
|
84
|
+
elsif load_balancer_pools.size > 1
|
85
|
+
print_red_alert "#{load_balancer_pools.size} #{load_balancer_pool_label_plural.downcase} found by name #{name}"
|
86
|
+
rows = load_balancer_pools.collect do |it|
|
87
|
+
{id: it['id'], name: it['name']}
|
88
|
+
end
|
89
|
+
puts as_pretty_table(rows, [:id, :name], {color:red})
|
90
|
+
return nil
|
91
|
+
else
|
92
|
+
return load_balancer_pools[0]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def format_load_balancer_pool_status(pool, return_color=cyan)
|
97
|
+
out = ""
|
98
|
+
status_string = pool['vipStatus'] || pool['status']
|
99
|
+
if status_string.nil? || status_string.empty? || status_string == "unknown"
|
100
|
+
out << "#{white}UNKNOWN#{return_color}"
|
101
|
+
elsif status_string == 'ok'
|
102
|
+
out << "#{green}#{status_string.upcase}#{return_color}"
|
103
|
+
elsif status_string == 'syncing'
|
104
|
+
out << "#{yellow}#{status_string.upcase}#{return_color}"
|
105
|
+
else
|
106
|
+
out << "#{red}#{status_string ? status_string.upcase : 'N/A'}#{pool['statusMessage'] ? "#{return_color} - #{pool['statusMessage']}" : ''}#{return_color}"
|
107
|
+
end
|
108
|
+
out
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
|
3
|
+
class Morpheus::Cli::LoadBalancerVirtualServers
|
4
|
+
include Morpheus::Cli::CliCommand
|
5
|
+
include Morpheus::Cli::RestCommand
|
6
|
+
# include Morpheus::Cli::SecondaryRestCommand
|
7
|
+
include Morpheus::Cli::LoadBalancersHelper
|
8
|
+
|
9
|
+
set_command_hidden # hide until ready
|
10
|
+
set_command_name :'load-balancer-virtual-servers'
|
11
|
+
register_subcommands :list, :get, :add, :update, :remove
|
12
|
+
|
13
|
+
register_interfaces :load_balancer_virtual_servers,
|
14
|
+
:load_balancers, :load_balancer_types
|
15
|
+
|
16
|
+
# set_rest_parent_name :load_balancers
|
17
|
+
|
18
|
+
# set_rest_interface_name :load_balancer_virtual_servers
|
19
|
+
# set_parent_rest_interface_name :load_balancers
|
20
|
+
|
21
|
+
# todo: a configurable way to load the optionTypes
|
22
|
+
# option_types = loadBalancer['vipOptionTypes']
|
23
|
+
# set_rest_has_type true
|
24
|
+
# set_rest_type :load_balancer_virtual_server_types
|
25
|
+
|
26
|
+
set_rest_arg 'vipName'
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def load_balancer_virtual_server_list_column_definitions()
|
31
|
+
{
|
32
|
+
"ID" => 'id',
|
33
|
+
"Name" => 'vipName',
|
34
|
+
"LB" => lambda {|it| it['loadBalancer'] ? it['loadBalancer']['name'] : '' },
|
35
|
+
# "Description" => 'description',
|
36
|
+
"Instance" => lambda {|it| it['instance'] ? it['instance']['name'] : '(Unassigned)' },
|
37
|
+
"Hostname" => lambda {|it| it['vipHostname'] },
|
38
|
+
"VIP" => lambda {|it| it['vipAddress'] },
|
39
|
+
"Protocol" => lambda {|it| it['vipProtocol'] },
|
40
|
+
"Port" => lambda {|it| it['vipPort'] },
|
41
|
+
"SSL" => lambda {|it| format_boolean(it['sslEnabled']) },
|
42
|
+
"Status" => lambda {|it| format_virtual_server_status(it) },
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def load_balancer_virtual_server_column_definitions()
|
47
|
+
{
|
48
|
+
"ID" => 'id',
|
49
|
+
"Name" => 'vipName',
|
50
|
+
"Description" => 'description',
|
51
|
+
"LB" => lambda {|it| it['loadBalancer'] ? it['loadBalancer']['name'] : '' },
|
52
|
+
"Instance" => lambda {|it| it['instance'] ? it['instance']['name'] : '(Unassigned)' },
|
53
|
+
"Hostname" => lambda {|it| it['vipHostname'] },
|
54
|
+
"VIP" => lambda {|it| it['vipAddress'] },
|
55
|
+
"Protocol" => lambda {|it| it['vipProtocol'] },
|
56
|
+
"Port" => lambda {|it| it['vipPort'] },
|
57
|
+
"SSL" => lambda {|it| format_boolean(it['sslEnabled']) },
|
58
|
+
# todo: more properties to show here
|
59
|
+
"Status" => lambda {|it| format_virtual_server_status(it) },
|
60
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
61
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def load_balancer_virtual_server_object_key
|
66
|
+
'virtualServer'
|
67
|
+
end
|
68
|
+
|
69
|
+
def load_balancer_virtual_server_list_key
|
70
|
+
'virtualServers'
|
71
|
+
end
|
72
|
+
|
73
|
+
def load_balancer_virtual_server_label
|
74
|
+
'Virtual Server'
|
75
|
+
end
|
76
|
+
|
77
|
+
def load_balancer_virtual_server_label_plural
|
78
|
+
'Virtual Servers'
|
79
|
+
end
|
80
|
+
|
81
|
+
def find_load_balancer_virtual_server_by_name_or_id(val)
|
82
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
83
|
+
return find_load_balancer_virtual_server_by_id(val)
|
84
|
+
else
|
85
|
+
return find_load_balancer_virtual_server_by_name(val)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def find_load_balancer_virtual_server_by_id(id)
|
90
|
+
begin
|
91
|
+
json_response = load_balancer_virtual_servers_interface.get(id.to_i)
|
92
|
+
return json_response[load_balancer_virtual_server_object_key]
|
93
|
+
rescue RestClient::Exception => e
|
94
|
+
if e.response && e.response.code == 404
|
95
|
+
print_red_alert "#{load_balancer_virtual_server_label} not found by id #{id}"
|
96
|
+
return nil
|
97
|
+
else
|
98
|
+
raise e
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def find_load_balancer_virtual_server_by_name(name)
|
104
|
+
json_response = load_balancer_virtual_servers_interface.list({name: name.to_s})
|
105
|
+
load_balancer_virtual_servers = json_response[load_balancer_virtual_server_list_key]
|
106
|
+
if load_balancer_virtual_servers.empty?
|
107
|
+
print_red_alert "#{load_balancer_virtual_server_label_plural} not found by name #{name}"
|
108
|
+
return load_balancer_virtual_servers
|
109
|
+
elsif load_balancer_virtual_servers.size > 1
|
110
|
+
print_red_alert "#{load_balancer_virtual_servers.size} #{load_balancer_virtual_server_label_plural.downcase} found by name #{name}"
|
111
|
+
rows = load_balancer_virtual_servers.collect do |it|
|
112
|
+
{id: it['id'], name: it['name']}
|
113
|
+
end
|
114
|
+
puts as_pretty_table(rows, [:id, :name], {color:red})
|
115
|
+
return nil
|
116
|
+
else
|
117
|
+
return load_balancer_virtual_servers[0]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def format_virtual_server_status(virtual_server, return_color=cyan)
|
122
|
+
out = ""
|
123
|
+
status_string = virtual_server['vipStatus'] || virtual_server['status']
|
124
|
+
if status_string.nil? || status_string.empty? || status_string == "unknown"
|
125
|
+
out << "#{white}UNKNOWN#{return_color}"
|
126
|
+
elsif status_string == 'ok'
|
127
|
+
out << "#{green}#{status_string.upcase}#{return_color}"
|
128
|
+
elsif status_string == 'syncing'
|
129
|
+
out << "#{yellow}#{status_string.upcase}#{return_color}"
|
130
|
+
else
|
131
|
+
out << "#{red}#{status_string ? status_string.upcase : 'N/A'}#{virtual_server['statusMessage'] ? "#{return_color} - #{virtual_server['statusMessage']}" : ''}#{return_color}"
|
132
|
+
end
|
133
|
+
out
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
@@ -42,161 +42,6 @@ class Morpheus::Cli::LoadBalancers
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
=begin
|
46
|
-
|
47
|
-
# now using RestCommand
|
48
|
-
|
49
|
-
def add(args)
|
50
|
-
lb_type_name = nil
|
51
|
-
options = {}
|
52
|
-
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
53
|
-
opts.banner = subcommand_usage("[name] -t LB_TYPE")
|
54
|
-
opts.on( '-t', '--type CODE', "Load Balancer Type" ) do |val|
|
55
|
-
lb_type_name = val
|
56
|
-
end
|
57
|
-
#build_option_type_options(opts, options, add_load_balancer_option_types)
|
58
|
-
build_standard_add_options(opts, options)
|
59
|
-
end
|
60
|
-
optparse.parse!(args)
|
61
|
-
lb_name = args[0]
|
62
|
-
# verify_args!(args:args, optparse:optparse, min:0, max: 1)
|
63
|
-
verify_args!(args:args, optparse:optparse, min:1, max: 1)
|
64
|
-
if lb_type_name.nil?
|
65
|
-
raise_command_error "Load Balancer Type is required.\n#{optparse}"
|
66
|
-
puts optparse
|
67
|
-
exit 1
|
68
|
-
end
|
69
|
-
connect(options)
|
70
|
-
lb_type = load_balancer_type_for_name_or_id(lb_type_name)
|
71
|
-
if lb_type.nil?
|
72
|
-
print_red_alert "LB Type #{lb_type_name} not found!"
|
73
|
-
exit 1
|
74
|
-
end
|
75
|
-
passed_options = parse_passed_options(options)
|
76
|
-
payload = {}
|
77
|
-
if options[:payload]
|
78
|
-
payload = options[:payload]
|
79
|
-
payload.deep_merge!({load_balancer_object_key => passed_options})
|
80
|
-
else
|
81
|
-
load_balancer_payload = {'name' => lb_name, 'type' => {'code' => lb_type['code'], 'id' => lb_type['id']}}
|
82
|
-
load_balancer_payload.deep_merge!({load_balancer_object_key => passed_options})
|
83
|
-
# options by type
|
84
|
-
my_option_types = lb_type['optionTypes']
|
85
|
-
if my_option_types && !my_option_types.empty?
|
86
|
-
v_prompt = Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, options[:params])
|
87
|
-
v_prompt.deep_compact!
|
88
|
-
load_balancer_payload.deep_merge!(v_prompt)
|
89
|
-
end
|
90
|
-
payload[load_balancer_object_key] = load_balancer_payload
|
91
|
-
end
|
92
|
-
@load_balancers_interface.setopts(options)
|
93
|
-
if options[:dry_run]
|
94
|
-
print_dry_run @load_balancers_interface.dry.create(payload)
|
95
|
-
return
|
96
|
-
end
|
97
|
-
json_response = @load_balancers_interface.create(payload)
|
98
|
-
render_response(json_response, options, load_balancer_object_key) do
|
99
|
-
load_balancer = json_response[load_balancer_object_key]
|
100
|
-
print_green_success "Added load balancer #{load_balancer['name']}"
|
101
|
-
return _get(load_balancer["id"], {}, options)
|
102
|
-
end
|
103
|
-
return 0, nil
|
104
|
-
end
|
105
|
-
|
106
|
-
def update(args)
|
107
|
-
lb_name = args[0]
|
108
|
-
options = {}
|
109
|
-
account_name = nil
|
110
|
-
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
111
|
-
opts.banner = subcommand_usage("[lb] [options]")
|
112
|
-
build_standard_update_options(opts, options)
|
113
|
-
end
|
114
|
-
optparse.parse!(args)
|
115
|
-
if args.count < 1
|
116
|
-
puts optparse
|
117
|
-
exit 1
|
118
|
-
end
|
119
|
-
connect(options)
|
120
|
-
|
121
|
-
passed_options = parse_passed_options(options)
|
122
|
-
payload = nil
|
123
|
-
if options[:payload]
|
124
|
-
payload = options[:payload]
|
125
|
-
payload.deep_merge!({load_balancer_object_key => passed_options}) unless passed_options.empty?
|
126
|
-
else
|
127
|
-
load_balancer_payload = passed_options
|
128
|
-
if tenants_list
|
129
|
-
load_balancer_payload['accounts'] = tenants_list
|
130
|
-
end
|
131
|
-
# metadata tags
|
132
|
-
if options[:tags]
|
133
|
-
load_balancer_payload['tags'] = parse_metadata(options[:tags])
|
134
|
-
else
|
135
|
-
# tags = prompt_metadata(options)
|
136
|
-
# payload[load_balancer_object_key]['tags'] = tags of tags
|
137
|
-
end
|
138
|
-
# metadata tags
|
139
|
-
if options[:add_tags]
|
140
|
-
load_balancer_payload['addTags'] = parse_metadata(options[:add_tags])
|
141
|
-
end
|
142
|
-
if options[:remove_tags]
|
143
|
-
load_balancer_payload['removeTags'] = parse_metadata(options[:remove_tags])
|
144
|
-
end
|
145
|
-
if load_balancer_payload.empty?
|
146
|
-
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
147
|
-
end
|
148
|
-
payload = {'virtualImage' => load_balancer_payload}
|
149
|
-
end
|
150
|
-
@load_balancers_interface.setopts(options)
|
151
|
-
if options[:dry_run]
|
152
|
-
print_dry_run @load_balancers_interface.dry.update(load_balancer['id'], payload)
|
153
|
-
return
|
154
|
-
end
|
155
|
-
json_response = @load_balancers_interface.update(load_balancer['id'], payload)
|
156
|
-
render_response(json_response, options, 'virtualImage') do
|
157
|
-
print_green_success "Updated virtual image #{load_balancer['name']}"
|
158
|
-
_get(load_balancer["id"], {}, options)
|
159
|
-
end
|
160
|
-
return 0, nil
|
161
|
-
end
|
162
|
-
|
163
|
-
def remove(args)
|
164
|
-
lb_name = args[0]
|
165
|
-
options = {}
|
166
|
-
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
167
|
-
opts.banner = subcommand_usage("[name]")
|
168
|
-
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
169
|
-
end
|
170
|
-
optparse.parse!(args)
|
171
|
-
if args.count < 1
|
172
|
-
puts optparse
|
173
|
-
exit 1
|
174
|
-
end
|
175
|
-
connect(options)
|
176
|
-
begin
|
177
|
-
lb = find_load_balancer_by_name_or_id(lb_name)
|
178
|
-
exit 1 if lb.nil?
|
179
|
-
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the load balancer #{lb['name']}?")
|
180
|
-
exit
|
181
|
-
end
|
182
|
-
@load_balancers_interface.setopts(options)
|
183
|
-
if options[:dry_run]
|
184
|
-
print_dry_run @load_balancers_interface.dry.destroy(lb['id'])
|
185
|
-
return
|
186
|
-
end
|
187
|
-
json_response = @load_balancers_interface.destroy(lb['id'])
|
188
|
-
if options[:json]
|
189
|
-
print JSON.pretty_generate(json_response), "\n"
|
190
|
-
else
|
191
|
-
print "\n", cyan, "Load Balancer #{lb['name']} removed", reset, "\n\n"
|
192
|
-
end
|
193
|
-
rescue RestClient::Exception => e
|
194
|
-
print_rest_exception(e, options)
|
195
|
-
exit 1
|
196
|
-
end
|
197
|
-
end
|
198
|
-
=end
|
199
|
-
|
200
45
|
# deprecated, to be removed in the future.
|
201
46
|
def types(args)
|
202
47
|
print_error yellow,"[DEPRECATED] The command `load-balancers types` is deprecated and replaced by `load-balancer-types list`.",reset,"\n"
|
@@ -34,7 +34,7 @@ module Morpheus::Cli::LoadBalancersHelper
|
|
34
34
|
'Load Balancer'
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
37
|
+
def load_balancer_label_plural
|
38
38
|
'Load Balancers'
|
39
39
|
end
|
40
40
|
|
@@ -50,7 +50,7 @@ module Morpheus::Cli::LoadBalancersHelper
|
|
50
50
|
'Load Balancer Type'
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
53
|
+
def load_balancer_type_label_plural
|
54
54
|
'Load Balancer Types'
|
55
55
|
end
|
56
56
|
|