morpheus-cli 5.4.5.1 → 5.5.1.1
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/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +12 -0
- data/lib/morpheus/api/backup_service_types_interface.rb +9 -0
- data/lib/morpheus/api/backup_services_interface.rb +9 -0
- data/lib/morpheus/api/clusters_interface.rb +12 -0
- data/lib/morpheus/api/network_pool_servers_interface.rb +7 -0
- data/lib/morpheus/api/prices_interface.rb +6 -0
- data/lib/morpheus/api/scale_thresholds_interface.rb +9 -0
- data/lib/morpheus/cli/cli_command.rb +55 -23
- data/lib/morpheus/cli/commands/apps.rb +1 -1
- data/lib/morpheus/cli/commands/backup_services_command.rb +44 -0
- data/lib/morpheus/cli/commands/cloud_resource_pools_command.rb +33 -2
- data/lib/morpheus/cli/commands/clouds.rb +67 -31
- data/lib/morpheus/cli/commands/clusters.rb +66 -5
- data/lib/morpheus/cli/commands/cypher_command.rb +22 -23
- data/lib/morpheus/cli/commands/hosts.rb +5 -1
- data/lib/morpheus/cli/commands/instances.rb +11 -11
- data/lib/morpheus/cli/commands/integrations_command.rb +1 -1
- data/lib/morpheus/cli/commands/invoices_command.rb +8 -1
- data/lib/morpheus/cli/commands/jobs_command.rb +45 -225
- data/lib/morpheus/cli/commands/library_container_types_command.rb +52 -3
- data/lib/morpheus/cli/commands/library_option_lists_command.rb +18 -8
- data/lib/morpheus/cli/commands/library_option_types_command.rb +56 -62
- data/lib/morpheus/cli/commands/load_balancers.rb +11 -19
- data/lib/morpheus/cli/commands/network_pool_servers_command.rb +5 -2
- data/lib/morpheus/cli/commands/prices_command.rb +25 -11
- data/lib/morpheus/cli/commands/roles.rb +475 -70
- data/lib/morpheus/cli/commands/scale_thresholds.rb +103 -0
- data/lib/morpheus/cli/commands/tasks.rb +64 -22
- data/lib/morpheus/cli/commands/user_sources_command.rb +107 -39
- data/lib/morpheus/cli/commands/users.rb +10 -10
- data/lib/morpheus/cli/commands/view.rb +1 -0
- data/lib/morpheus/cli/commands/workflows.rb +21 -14
- data/lib/morpheus/cli/error_handler.rb +13 -4
- data/lib/morpheus/cli/mixins/accounts_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/execution_request_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/infrastructure_helper.rb +3 -3
- data/lib/morpheus/cli/mixins/jobs_helper.rb +173 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +120 -38
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +2 -3
- data/lib/morpheus/cli/mixins/rest_command.rb +58 -15
- data/lib/morpheus/cli/option_types.rb +69 -13
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/logging.rb +6 -8
- data/lib/morpheus/routes.rb +3 -5
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a66201f045d6e88db90746058ce40000b064616975aae3d00c025069c51f20d7
|
4
|
+
data.tar.gz: de2b69e5a52ca31f7bde8d573428853a765668b2d08ba8eaca1cdbe6743ecf0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebc460c1903caf068710ac2512e73fb88329045a49ff603904e875ff2a02cb6a4ec02b34195d9ee19c98ab8eefb6388357d8c43cb69a8ad92891322a085f1dd1
|
7
|
+
data.tar.gz: 60a297a75a29a6bb53a3944b81fa14a9f46c846173bf98472886bb86a5a13491c55da9600fa691d861ba20812546b5d57e891a61a3b4dcef9c922ed3b43a3f9b
|
data/Dockerfile
CHANGED
@@ -590,6 +590,10 @@ class Morpheus::APIClient
|
|
590
590
|
Morpheus::OptionTypeListsInterface.new(common_interface_options).setopts(@options)
|
591
591
|
end
|
592
592
|
|
593
|
+
def scale_thresholds
|
594
|
+
Morpheus::ScaleThresholdsInterface.new(common_interface_options).setopts(@options)
|
595
|
+
end
|
596
|
+
|
593
597
|
def power_schedules
|
594
598
|
Morpheus::PowerSchedulesInterface.new(common_interface_options).setopts(@options)
|
595
599
|
end
|
@@ -832,6 +836,14 @@ class Morpheus::APIClient
|
|
832
836
|
Morpheus::BackupJobsInterface.new(common_interface_options).setopts(@options)
|
833
837
|
end
|
834
838
|
|
839
|
+
def backup_services
|
840
|
+
Morpheus::BackupServicesInterface.new(common_interface_options).setopts(@options)
|
841
|
+
end
|
842
|
+
|
843
|
+
def backup_service_types
|
844
|
+
Morpheus::BackupServiceTypesInterface.new(common_interface_options).setopts(@options)
|
845
|
+
end
|
846
|
+
|
835
847
|
def catalog_item_types
|
836
848
|
Morpheus::CatalogItemTypesInterface.new(common_interface_options).setopts(@options)
|
837
849
|
end
|
@@ -103,6 +103,18 @@ class Morpheus::ClustersInterface < Morpheus::APIClient
|
|
103
103
|
execute(method: :put, url: url, headers: headers)
|
104
104
|
end
|
105
105
|
|
106
|
+
def get_upgrade_versions(id, params={})
|
107
|
+
url = "#{base_path}/#{id}/upgrade-cluster"
|
108
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
109
|
+
execute(method: :get, url: url, headers: headers)
|
110
|
+
end
|
111
|
+
|
112
|
+
def do_cluster_upgrade(id, params={})
|
113
|
+
url = "#{base_path}/#{id}/upgrade-cluster"
|
114
|
+
headers = { params: params, authorization: "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
115
|
+
execute(method: :post, url: url, headers: headers)
|
116
|
+
end
|
117
|
+
|
106
118
|
def list_services(id, params={})
|
107
119
|
url = "#{base_path}/#{id}/services"
|
108
120
|
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
@@ -38,4 +38,11 @@ class Morpheus::NetworkPoolServersInterface < Morpheus::APIClient
|
|
38
38
|
execute(opts)
|
39
39
|
end
|
40
40
|
|
41
|
+
def get_type(id, params={})
|
42
|
+
raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
|
43
|
+
url = "#{@base_url}/api/networks/pool-server-types/#{id}"
|
44
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
45
|
+
opts = {method: :get, url: url, headers: headers}
|
46
|
+
execute(opts)
|
47
|
+
end
|
41
48
|
end
|
@@ -62,4 +62,10 @@ class Morpheus::PricesInterface < Morpheus::APIClient
|
|
62
62
|
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
63
63
|
execute(method: :get, url: url, headers: headers)
|
64
64
|
end
|
65
|
+
|
66
|
+
def list_currencies(params={})
|
67
|
+
url = "#{base_path}/currencies"
|
68
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
69
|
+
execute(method: :get, url: url, headers: headers)
|
70
|
+
end
|
65
71
|
end
|
@@ -253,7 +253,7 @@ module Morpheus
|
|
253
253
|
|
254
254
|
# list is GET that supports phrase,max,offset,sort,direction
|
255
255
|
def build_standard_list_options(opts, options, includes=[], excludes=[])
|
256
|
-
build_standard_get_options(opts, options, [:list] + includes, excludes
|
256
|
+
build_standard_get_options(opts, options, [:list] + includes, excludes)
|
257
257
|
end
|
258
258
|
|
259
259
|
def build_standard_add_options(opts, options, includes=[], excludes=[])
|
@@ -479,8 +479,10 @@ module Morpheus
|
|
479
479
|
options[:offset] = offset
|
480
480
|
end
|
481
481
|
|
482
|
-
|
483
|
-
|
482
|
+
if excludes.include?("search") == false
|
483
|
+
opts.on( '-s', '--search PHRASE', "Search Phrase" ) do |phrase|
|
484
|
+
options[:phrase] = phrase
|
485
|
+
end
|
484
486
|
end
|
485
487
|
|
486
488
|
opts.on( '-S', '--sort ORDER', "Sort Order. DIRECTION may be included as \"ORDER [asc|desc]\"." ) do |v|
|
@@ -741,7 +743,15 @@ module Morpheus
|
|
741
743
|
options[:include_fields] = val
|
742
744
|
end
|
743
745
|
end
|
744
|
-
opts.
|
746
|
+
opts.on('--raw-fields [x,y,z]', String, "Raw fields filters output like --fields except the properties [x,y,z] must be specified from the root of the response instead of relative to the the list or object context for this particular resource.") do |val|
|
747
|
+
if val.size == 1 && val[0].downcase == 'all'
|
748
|
+
options[:all_fields] = true
|
749
|
+
else
|
750
|
+
options[:include_fields] = val.split(',').collect {|r| r.strip}.compact
|
751
|
+
end
|
752
|
+
options[:raw_fields] = true
|
753
|
+
end
|
754
|
+
opts.add_hidden_option('--raw-fields') if opts.is_a?(Morpheus::Cli::OptionParser)
|
745
755
|
opts.on(nil, '--all-fields', "Show all fields present in the data.") do
|
746
756
|
options[:all_fields] = true
|
747
757
|
end
|
@@ -753,6 +763,11 @@ module Morpheus
|
|
753
763
|
opts.on('--select x,y,z', String, "Filter Output to just print the value(s) of specific fields.") do |val|
|
754
764
|
options[:select_fields] = val.split(',').collect {|r| r.strip}
|
755
765
|
end
|
766
|
+
opts.on('--raw-select x,y,z', String, "Raw select works like --select except the properties [x,y,z] must be specified from the root of the response instead of relative to the the list or object context for this particular resource.") do |val|
|
767
|
+
options[:select_fields] = val.split(',').collect {|r| r.strip}
|
768
|
+
options[:raw_fields] = true
|
769
|
+
end
|
770
|
+
opts.add_hidden_option('--raw-select') if opts.is_a?(Morpheus::Cli::OptionParser)
|
756
771
|
|
757
772
|
when :delim
|
758
773
|
opts.on('--delimiter [CHAR]', String, "Delimiter for output values. Default: ',', use with --select and --csv") do |val|
|
@@ -1397,29 +1412,33 @@ module Morpheus
|
|
1397
1412
|
def render_response(json_response, options, object_key=nil, &block)
|
1398
1413
|
output = nil
|
1399
1414
|
if options[:select_fields]
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1415
|
+
# support foos get --raw-select foo.x,foo.y,foo.z
|
1416
|
+
# and foos list --raw-select foos.x,foos.y,foos.z
|
1417
|
+
row = (object_key && !options[:raw_fields]) ? json_response[object_key] : json_response
|
1418
|
+
records = [row].flatten()
|
1419
|
+
# look for an array in the first field only now...
|
1420
|
+
field_parts = options[:select_fields][0].to_s.split(".")
|
1421
|
+
field_context = field_parts[0]
|
1422
|
+
context_data = json_response[field_context]
|
1423
|
+
if field_parts.size > 1 && context_data.is_a?(Array)
|
1424
|
+
# inject all the root level properties to be selectable too..
|
1425
|
+
context_data = json_response.delete(field_context)
|
1426
|
+
# records = context_data
|
1427
|
+
records = context_data.collect {|it| it.is_a?(Hash) ? json_response.merge(it) : json_response }
|
1428
|
+
options[:select_fields] = options[:select_fields].collect {|it| it.sub(field_context+'.', '')}
|
1411
1429
|
end
|
1430
|
+
output = records.collect { |record|
|
1431
|
+
options[:select_fields].collect { |field|
|
1432
|
+
value = get_object_value(record, field)
|
1433
|
+
value.is_a?(String) ? value : JSON.fast_generate(value)
|
1434
|
+
}.join(options[:delim] || ",")
|
1435
|
+
}.join(options[:newline] || "\n")
|
1412
1436
|
elsif options[:json]
|
1413
1437
|
output = as_json(json_response, options, object_key)
|
1414
1438
|
elsif options[:yaml]
|
1415
1439
|
output = as_yaml(json_response, options, object_key)
|
1416
1440
|
elsif options[:csv]
|
1417
|
-
|
1418
|
-
if row.is_a?(Array)
|
1419
|
-
output = records_as_csv(row, options)
|
1420
|
-
else
|
1421
|
-
output = records_as_csv([row], options)
|
1422
|
-
end
|
1441
|
+
output = as_csv(json_response, nil, options, object_key)
|
1423
1442
|
end
|
1424
1443
|
if options[:outfile]
|
1425
1444
|
full_outfile = File.expand_path(options[:outfile])
|
@@ -1569,7 +1588,7 @@ module Morpheus
|
|
1569
1588
|
#Morpheus::Logging::DarkPrinter.puts "find_all(#{args.join(', ')})" if Morpheus::Logging.debug?
|
1570
1589
|
type, *request_args = args
|
1571
1590
|
type = type.to_s.singularize.underscore
|
1572
|
-
list_key = respond_to?("#{type}_list_key", true) ? send("#{type}_list_key") : type
|
1591
|
+
list_key = respond_to?("#{type}_list_key", true) ? send("#{type}_list_key") : get_list_key(type)
|
1573
1592
|
json_response = find_all_json(*args)
|
1574
1593
|
if !json_response.key?(list_key)
|
1575
1594
|
# maybe just use the first key like this:
|
@@ -1600,7 +1619,7 @@ module Morpheus
|
|
1600
1619
|
#Morpheus::Logging::DarkPrinter.puts "find_record(#{args.join(', ')})" if Morpheus::Logging.debug?
|
1601
1620
|
type, *request_args = args
|
1602
1621
|
type = type.to_s.singularize.underscore
|
1603
|
-
object_key = respond_to?("#{type}_object_key", true) ? send("#{type}_object_key") : type
|
1622
|
+
object_key = respond_to?("#{type}_object_key", true) ? send("#{type}_object_key") : get_object_key(type)
|
1604
1623
|
json_response = find_record_json(*args)
|
1605
1624
|
if !json_response.key?(object_key)
|
1606
1625
|
# maybe just use the first key like this:
|
@@ -1645,6 +1664,19 @@ module Morpheus
|
|
1645
1664
|
return interface
|
1646
1665
|
end
|
1647
1666
|
|
1667
|
+
def get_list_key(type)
|
1668
|
+
return get_object_key(type).pluralize
|
1669
|
+
end
|
1670
|
+
|
1671
|
+
def get_object_key(type)
|
1672
|
+
key = type.camelcase.singularize
|
1673
|
+
# add aliases here as needed
|
1674
|
+
if key == "cloud"
|
1675
|
+
key = "zone"
|
1676
|
+
end
|
1677
|
+
return key
|
1678
|
+
end
|
1679
|
+
|
1648
1680
|
module ClassMethods
|
1649
1681
|
|
1650
1682
|
def prog_name
|
@@ -996,7 +996,7 @@ EOT
|
|
996
996
|
end
|
997
997
|
|
998
998
|
def apply(args)
|
999
|
-
default_refresh_interval =
|
999
|
+
default_refresh_interval = 10
|
1000
1000
|
params, payload, options = {}, {}, {}
|
1001
1001
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1002
1002
|
opts.banner = subcommand_usage("[app] [options]")
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
|
3
|
+
class Morpheus::Cli::BackupServices
|
4
|
+
include Morpheus::Cli::CliCommand
|
5
|
+
include Morpheus::Cli::RestCommand
|
6
|
+
|
7
|
+
set_command_description "View and manage backup services."
|
8
|
+
set_command_name :'backup-services'
|
9
|
+
register_subcommands :list, :get, :add, :update, :remove
|
10
|
+
register_interfaces :backup_services, :backup_service_types
|
11
|
+
set_rest_has_type true
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def load_option_types_for_backup_service(record_type, parent_record)
|
16
|
+
[
|
17
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
18
|
+
{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'defaultValue' => 'on', 'displayOrder' => 2},
|
19
|
+
{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Public', 'value' => 'public'}, {'name' => 'Private', 'value' => 'private'}], 'defaultValue' => 'public', 'displayOrder' => 1000}
|
20
|
+
] + record_type['optionTypes']
|
21
|
+
end
|
22
|
+
|
23
|
+
def backup_service_list_column_definitions(options)
|
24
|
+
{
|
25
|
+
"ID" => 'id',
|
26
|
+
"Name" => 'name',
|
27
|
+
"Status" => 'status',
|
28
|
+
"Visibility" => 'visibility'
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def backup_service_column_definitions(options)
|
33
|
+
{
|
34
|
+
"ID" => 'id',
|
35
|
+
"Name" => 'name',
|
36
|
+
"Enabled" => 'enabled',
|
37
|
+
"Api URL" => 'serviceUrl',
|
38
|
+
"Host" => 'host',
|
39
|
+
"Port" => 'port',
|
40
|
+
"Credential" => lambda {|it| it['credential']['type'] == 'local' ? 'local' : it['credential']['name']},
|
41
|
+
"Visibility" => 'visibility'
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
@@ -35,7 +35,10 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
35
35
|
cloud_id = val
|
36
36
|
end
|
37
37
|
opts.add_hidden_option('-c') # prefer args[0] for [cloud]
|
38
|
-
|
38
|
+
opts.on( '-s', '--search PHRASE', "Search by Name and/or Display Name" ) do |phrase|
|
39
|
+
options[:phrase] = phrase
|
40
|
+
end
|
41
|
+
build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote], ['search'])
|
39
42
|
opts.footer = "List resource pools for a cloud." + "\n" +
|
40
43
|
"[cloud] is required. This is the name or id of the cloud."
|
41
44
|
end
|
@@ -91,6 +94,7 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
91
94
|
type: resource_pool['type'].to_s.capitalize,
|
92
95
|
description: resource_pool['description'],
|
93
96
|
active: format_boolean(resource_pool['active']),
|
97
|
+
inventory: format_boolean(resource_pool['inventory']),
|
94
98
|
status: resource_pool['status'].to_s.upcase,
|
95
99
|
visibility: resource_pool['visibility'].to_s.capitalize,
|
96
100
|
default: format_boolean(resource_pool['defaultPool']),
|
@@ -99,7 +103,7 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
99
103
|
}
|
100
104
|
row
|
101
105
|
}
|
102
|
-
columns = [:id, :name, :description, :active, :default, :visibility, :tenants]
|
106
|
+
columns = [:id, :name, :description, :active,:inventory, :default, :visibility, :tenants]
|
103
107
|
if options[:include_fields]
|
104
108
|
columns = options[:include_fields]
|
105
109
|
end
|
@@ -179,10 +183,12 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
179
183
|
description_cols = {
|
180
184
|
"ID" => 'id',
|
181
185
|
"Name" => 'name',
|
186
|
+
"Display Name" => 'displayName',
|
182
187
|
"Description" => 'description',
|
183
188
|
#"Type" => lambda {|it| it['type'].to_s.capitalize },
|
184
189
|
"Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
|
185
190
|
"Active" => lambda {|it| format_boolean(it['active']) },
|
191
|
+
"Inventory" => lambda {|it| format_boolean(it['inventory']) },
|
186
192
|
"Default" => lambda {|it| format_boolean(it['defaultPool']) },
|
187
193
|
"Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
|
188
194
|
"Status" => lambda {|it| it['status'].to_s.capitalize },
|
@@ -329,6 +335,9 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
329
335
|
opts.on('--active [on|off]', String, "Can be used to disable a resource pool") do |val|
|
330
336
|
options['active'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
331
337
|
end
|
338
|
+
opts.on('--inventory [on|off]', String, "Enable or disable inventory sync for resource pool during cloud refresh") do |val|
|
339
|
+
options['inventory'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
340
|
+
end
|
332
341
|
opts.on('--default-pool [on|off]', String, "Set resource pool as the default") do |val|
|
333
342
|
options['defaultPool'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
334
343
|
end
|
@@ -447,6 +456,11 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
447
456
|
else
|
448
457
|
payload['resourcePool']['active'] = true
|
449
458
|
end
|
459
|
+
|
460
|
+
#inventory
|
461
|
+
if options['inventory'] != nil
|
462
|
+
payload['resourcePool']['inventory'] = options['inventory']
|
463
|
+
end
|
450
464
|
|
451
465
|
# Default
|
452
466
|
if options['defaultPool'] != nil
|
@@ -574,12 +588,18 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
574
588
|
opts.on('--active [on|off]', String, "Can be used to disable a resource pool") do |val|
|
575
589
|
options['active'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
576
590
|
end
|
591
|
+
opts.on('--inventory [on|off]', String, "Enable or disable inventory sync for resource pool during cloud refresh") do |val|
|
592
|
+
options['inventory'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
593
|
+
end
|
577
594
|
opts.on('--default-pool [on|off]', String, "Set resource pool as the default") do |val|
|
578
595
|
options['defaultPool'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
579
596
|
end
|
580
597
|
opts.on("--description [TEXT]", String, "Description") do |val|
|
581
598
|
options['description'] = val.to_s
|
582
599
|
end
|
600
|
+
opts.on("--display-name [TEXT]", String, "Display Name") do |val|
|
601
|
+
options['displayName'] = val.to_s
|
602
|
+
end
|
583
603
|
opts.on( '--role ROLE', String, "Role Name or ID (applicable to select resource pools)" ) do |val|
|
584
604
|
options['role'] = val
|
585
605
|
end
|
@@ -599,6 +619,7 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
599
619
|
end
|
600
620
|
|
601
621
|
connect(options)
|
622
|
+
puts "options #{options}"
|
602
623
|
|
603
624
|
begin
|
604
625
|
# load cloud
|
@@ -672,6 +693,11 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
672
693
|
if options['active'] != nil
|
673
694
|
payload['resourcePool']['active'] = options['active']
|
674
695
|
end
|
696
|
+
|
697
|
+
#inventory
|
698
|
+
if options['inventory'] != nil
|
699
|
+
payload['resourcePool']['inventory'] = options['inventory']
|
700
|
+
end
|
675
701
|
|
676
702
|
# Default
|
677
703
|
if options['defaultPool'] != nil
|
@@ -688,6 +714,11 @@ class Morpheus::Cli::CloudResourcePoolsCommand
|
|
688
714
|
payload['resourcePool']['description'] = options['description']
|
689
715
|
end
|
690
716
|
|
717
|
+
# Display Name
|
718
|
+
if options['displayName'] != nil
|
719
|
+
payload['resourcePool']['displayName'] = options['displayName']
|
720
|
+
end
|
721
|
+
|
691
722
|
# Role
|
692
723
|
if options['role'] != nil
|
693
724
|
role_options = load_option_source_data('openstackRoles', {zoneId: cloud['id']})
|
@@ -80,8 +80,9 @@ class Morpheus::Cli::Clouds
|
|
80
80
|
print_h1 title, subtitles
|
81
81
|
if clouds.empty?
|
82
82
|
print cyan,"No clouds found.",reset,"\n"
|
83
|
-
else
|
84
|
-
|
83
|
+
else
|
84
|
+
columns = cloud_list_column_definitions(options).upcase_keys!
|
85
|
+
print as_pretty_table(clouds, columns, options)
|
85
86
|
print_results_pagination(json_response)
|
86
87
|
end
|
87
88
|
print reset,"\n"
|
@@ -164,13 +165,14 @@ class Morpheus::Cli::Clouds
|
|
164
165
|
else
|
165
166
|
server_counts = json_response['serverCounts'] # legacy
|
166
167
|
end
|
167
|
-
cloud_type = cloud_type_for_id(cloud['zoneTypeId'])
|
168
|
+
#cloud_type = cloud_type_for_id(cloud['zoneTypeId'])
|
168
169
|
print_h1 "Cloud Details"
|
169
170
|
print cyan
|
170
171
|
description_cols = {
|
171
172
|
"ID" => 'id',
|
172
173
|
"Name" => 'name',
|
173
|
-
"Type" => lambda {|it| cloud_type ? cloud_type['name'] : '' },
|
174
|
+
# "Type" => lambda {|it| cloud_type ? cloud_type['name'] : '' },
|
175
|
+
"Type" => lambda {|it| it['zoneType'] ? it['zoneType']['name'] : '' },
|
174
176
|
"Code" => 'code',
|
175
177
|
"Location" => 'location',
|
176
178
|
"Region Code" => 'regionCode',
|
@@ -215,6 +217,13 @@ class Morpheus::Cli::Clouds
|
|
215
217
|
opts.on( '--certificate-provider CODE', String, "Certificate Provider. Default is 'internal'" ) do |val|
|
216
218
|
params[:certificate_provider] = val
|
217
219
|
end
|
220
|
+
opts.on('--costing-mode VALUE', String, "Costing Mode can be off,costing,full, Default is off." ) do |val|
|
221
|
+
options[:options]['costingMode'] = val
|
222
|
+
end
|
223
|
+
opts.on('--credential VALUE', String, "Credential ID or \"local\"" ) do |val|
|
224
|
+
options[:options]['credential'] = val
|
225
|
+
end
|
226
|
+
|
218
227
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
219
228
|
end
|
220
229
|
optparse.parse!(args)
|
@@ -251,7 +260,6 @@ class Morpheus::Cli::Clouds
|
|
251
260
|
# todo: pass groups as an array instead
|
252
261
|
|
253
262
|
# Cloud Name
|
254
|
-
|
255
263
|
if args[0]
|
256
264
|
cloud_payload[:name] = args[0]
|
257
265
|
options[:options]['name'] = args[0] # to skip prompt
|
@@ -261,7 +269,6 @@ class Morpheus::Cli::Clouds
|
|
261
269
|
end
|
262
270
|
|
263
271
|
# Cloud Type
|
264
|
-
|
265
272
|
cloud_type = nil
|
266
273
|
if params[:zone_type]
|
267
274
|
cloud_type = cloud_type_for_name(params[:zone_type])
|
@@ -329,6 +336,12 @@ class Morpheus::Cli::Clouds
|
|
329
336
|
# opts.on( '-d', '--description DESCRIPTION', "Description (optional)" ) do |desc|
|
330
337
|
# params[:description] = desc
|
331
338
|
# end
|
339
|
+
opts.on('--costing-mode VALUE', String, "Costing Mode can be off, costing, or full. Default is off." ) do |val|
|
340
|
+
options[:options]['costingMode'] = val
|
341
|
+
end
|
342
|
+
opts.on('--credential VALUE', String, "Credential ID or \"local\"" ) do |val|
|
343
|
+
options[:options]['credential'] = val
|
344
|
+
end
|
332
345
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
333
346
|
end
|
334
347
|
optparse.parse!(args)
|
@@ -352,12 +365,26 @@ class Morpheus::Cli::Clouds
|
|
352
365
|
cloud_type = cloud_type_for_id(cloud['zoneTypeId'])
|
353
366
|
cloud_payload = {}
|
354
367
|
all_option_types = update_cloud_option_types(cloud_type)
|
355
|
-
#params = Morpheus::Cli::OptionTypes.
|
368
|
+
#params = Morpheus::Cli::OptionTypes.no_prompt(all_option_types, options[:options], @api_client, {zoneId: cloud['id'], zoneTypeId: cloud_type['id']})
|
356
369
|
params = options[:options] || {}
|
370
|
+
|
371
|
+
# Credentials (ideally only if value passed in and name can be parsed)
|
372
|
+
if options[:options]['credential']
|
373
|
+
credential_code = "credential"
|
374
|
+
credential_option_type = {'code' => credential_code, 'fieldName' => credential_code, 'fieldLabel' => 'Credentials', 'type' => 'select', 'optionSource' => 'credentials', 'description' => 'Enter an existing credential ID or choose "local"', 'defaultValue' => "local", 'required' => true}
|
375
|
+
# supported_credential_types = ['username-keypair', 'username-password', 'username-password-keypair'].compact.flatten.join(",").split(",").collect {|it| it.strip }
|
376
|
+
credential_params = {"new" => false, "zoneId" => cloud['id']}
|
377
|
+
credential_value = Morpheus::Cli::OptionTypes.select_prompt(credential_option_type, @api_client, credential_params, true, options[:options][credential_code])
|
378
|
+
if !credential_value.to_s.empty?
|
379
|
+
if credential_value == "local"
|
380
|
+
params[credential_code] = {"type" => credential_value}
|
381
|
+
elsif credential_value.to_s =~ /\A\d{1,}\Z/
|
382
|
+
params[credential_code] = {"id" => credential_value.to_i}
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
357
386
|
if params.empty?
|
358
|
-
|
359
|
-
puts_error format_available_options(all_option_types)
|
360
|
-
exit 1
|
387
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
361
388
|
end
|
362
389
|
# some optionTypes have fieldContext='zone', so move those to the root level of the zone payload
|
363
390
|
if params['zone'].is_a?(Hash)
|
@@ -430,7 +457,16 @@ class Morpheus::Cli::Clouds
|
|
430
457
|
query_params = {}
|
431
458
|
params = {}
|
432
459
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
433
|
-
opts.banner = subcommand_usage("[
|
460
|
+
opts.banner = subcommand_usage("[cloud] [options]")
|
461
|
+
opts.on( '-m', '--mode [daily|costing]', "Refresh Mode. Use this to run the daily or costing jobs instead of the default hourly refresh." ) do |val|
|
462
|
+
query_params[:mode] = val
|
463
|
+
end
|
464
|
+
opts.on( '--rebuild [on|off]', "Rebuild invoices for period. Only applies to mode=costing." ) do |val|
|
465
|
+
query_params[:rebuild] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
466
|
+
end
|
467
|
+
opts.on( '--period PERIOD', "Period in the format YYYYMM to process invoices for. Default is the current period. Only applies to mode=costing." ) do |val|
|
468
|
+
query_params[:period] = val.to_s
|
469
|
+
end
|
434
470
|
opts.on( '-f', '--force', "Force refresh. Useful if the cloud is disabled." ) do
|
435
471
|
query_params[:force] = 'true'
|
436
472
|
end
|
@@ -919,25 +955,17 @@ class Morpheus::Cli::Clouds
|
|
919
955
|
|
920
956
|
private
|
921
957
|
|
922
|
-
def
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
{
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
servers: cloud['serverCount'],
|
934
|
-
status: format_cloud_status(cloud)
|
935
|
-
}
|
936
|
-
end
|
937
|
-
columns = [
|
938
|
-
:id, :name, :type, :location, "REGION CODE", :groups, :servers, :status
|
939
|
-
]
|
940
|
-
print as_pretty_table(rows, columns, opts)
|
958
|
+
def cloud_list_column_definitions(options)
|
959
|
+
{
|
960
|
+
"ID" => 'id',
|
961
|
+
"Name" => 'name',
|
962
|
+
"Type" => lambda {|it| it['zoneType'] ? it['zoneType']['name'] : '' },
|
963
|
+
"Location" => 'location',
|
964
|
+
"Region Code" => lambda {|it| it['regionCode'] },
|
965
|
+
"Groups" => lambda {|it| (it['groups'] || []).collect {|g| g.instance_of?(Hash) ? g['name'] : g.to_s }.join(', ') },
|
966
|
+
"Servers" => lambda {|it| it['serverCount'] },
|
967
|
+
"Status" => lambda {|it| format_cloud_status(it) },
|
968
|
+
}
|
941
969
|
end
|
942
970
|
|
943
971
|
def add_cloud_option_types(cloud_type)
|
@@ -948,6 +976,8 @@ class Morpheus::Cli::Clouds
|
|
948
976
|
{'fieldName' => 'code', 'fieldLabel' => 'Code', 'type' => 'text', 'required' => false, 'displayOrder' => 2},
|
949
977
|
{'fieldName' => 'location', 'fieldLabel' => 'Location', 'type' => 'text', 'required' => false, 'displayOrder' => 3},
|
950
978
|
{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'},{'name' => 'Public', 'value' => 'public'}], 'required' => false, 'description' => 'Visibility', 'category' => 'permissions', 'defaultValue' => 'private', 'displayOrder' => 4},
|
979
|
+
{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'required' => false, 'defaultValue' => true, 'displayOrder' => 5},
|
980
|
+
{'fieldName' => 'autoRecoverPowerState', 'fieldLabel' => 'Automatically Power On VMs', 'type' => 'checkbox', 'required' => false, 'defaultValue' => false, 'displayOrder' => 6}
|
951
981
|
]
|
952
982
|
|
953
983
|
# TODO: Account
|
@@ -955,9 +985,15 @@ class Morpheus::Cli::Clouds
|
|
955
985
|
# Details (zoneType.optionTypes)
|
956
986
|
|
957
987
|
if cloud_type && cloud_type['optionTypes']
|
988
|
+
if !cloud_type['optionTypes'].find {|opt| opt['type'] == 'credential'}
|
989
|
+
tmp_option_types << {'fieldName' => 'type', 'fieldLabel' => 'Credentials', 'type' => 'credential', 'optionSource' => 'credentials', 'required' => true, 'defaultValue' => 'local', 'config' => {'credentialTypes' => ['username-password']}, 'displayOrder' => 7}
|
990
|
+
cloud_type['optionTypes'].select {|opt| ['username', 'password'].include?(opt['fieldName'])}.each {|opt| opt['localCredential'] = true}
|
991
|
+
end
|
958
992
|
# adjust displayOrder to put these at the end
|
959
993
|
#tmp_option_types = tmp_option_types + cloud_type['optionTypes']
|
960
994
|
cloud_type['optionTypes'].each do |opt|
|
995
|
+
# temp fix for typo
|
996
|
+
opt['optionSource'] = 'credentials' if opt['optionSource'] == 'credentials,'
|
961
997
|
tmp_option_types << opt.merge({'displayOrder' => opt['displayOrder'].to_i + 100})
|
962
998
|
end
|
963
999
|
end
|
@@ -980,7 +1016,7 @@ class Morpheus::Cli::Clouds
|
|
980
1016
|
end
|
981
1017
|
|
982
1018
|
def cloud_types_for_dropdown
|
983
|
-
|
1019
|
+
@clouds_interface.cloud_types({max:1000, shallow:true})['zoneTypes'].select {|it| it['enabled'] }.collect {|it| {'name' => it['name'], 'value' => it['code']} }
|
984
1020
|
end
|
985
1021
|
|
986
1022
|
def format_cloud_status(cloud, return_color=cyan)
|