morpheus-cli 5.5.3.1 → 6.0.0
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 +8 -0
- data/lib/morpheus/api/cloud_resource_pools_interface.rb +28 -3
- data/lib/morpheus/api/containers_interface.rb +10 -0
- data/lib/morpheus/api/doc_interface.rb +1 -10
- data/lib/morpheus/api/key_pairs_interface.rb +9 -0
- data/lib/morpheus/api/network_floating_ips_interface.rb +37 -0
- data/lib/morpheus/api/resource_pool_groups_interface.rb +51 -0
- data/lib/morpheus/cli/cli_command.rb +17 -11
- data/lib/morpheus/cli/commands/appliance_settings_command.rb +5 -0
- data/lib/morpheus/cli/commands/apps.rb +11 -5
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +42 -12
- data/lib/morpheus/cli/commands/clusters.rb +23 -2
- data/lib/morpheus/cli/commands/containers_command.rb +129 -4
- data/lib/morpheus/cli/commands/doc.rb +14 -13
- data/lib/morpheus/cli/commands/hosts.rb +2 -0
- data/lib/morpheus/cli/commands/instances.rb +8 -2
- data/lib/morpheus/cli/commands/key_pairs.rb +94 -33
- data/lib/morpheus/cli/commands/network_floating_ips.rb +109 -0
- data/lib/morpheus/cli/commands/reports_command.rb +8 -1
- data/lib/morpheus/cli/commands/resource_pool_groups_command.rb +586 -0
- data/lib/morpheus/cli/commands/roles.rb +10 -10
- data/lib/morpheus/cli/commands/service_catalog_command.rb +44 -2
- data/lib/morpheus/cli/commands/tasks.rb +1 -1
- data/lib/morpheus/cli/commands/workflows.rb +1 -1
- data/lib/morpheus/cli/credentials.rb +2 -1
- data/lib/morpheus/cli/mixins/infrastructure_helper.rb +148 -0
- data/lib/morpheus/cli/option_types.rb +15 -8
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli.rb +13 -0
- data/test/cli/doc_test.rb +1 -1
- data/test/test_case.rb +3 -0
- metadata +6 -2
@@ -661,7 +661,8 @@ EOT
|
|
661
661
|
it
|
662
662
|
}
|
663
663
|
if catalog_option_types && !catalog_option_types.empty?
|
664
|
-
|
664
|
+
api_params = construct_catalog_api_params(catalog_item_type)
|
665
|
+
config_prompt = Morpheus::Cli::OptionTypes.prompt(catalog_option_types, options[:options], @api_client, api_params, options[:no_prompt], false, false, true)['config']
|
665
666
|
payload[add_item_object_key].deep_merge!({'config' => config_prompt})
|
666
667
|
end
|
667
668
|
if workflow_context
|
@@ -999,11 +1000,13 @@ EOT
|
|
999
1000
|
catalog_option_types = catalog_item_type['optionTypes']
|
1000
1001
|
# instead of config.customOptions just use config...
|
1001
1002
|
catalog_option_types = catalog_option_types.collect {|it|
|
1003
|
+
it['fieldContext'] = nil
|
1002
1004
|
it['fieldContext'] = 'config'
|
1003
1005
|
it
|
1004
1006
|
}
|
1005
1007
|
if catalog_option_types && !catalog_option_types.empty?
|
1006
|
-
|
1008
|
+
api_params = construct_catalog_api_params(catalog_item_type)
|
1009
|
+
config_prompt = Morpheus::Cli::OptionTypes.prompt(catalog_option_types, options[:options], @api_client, api_params, options[:no_prompt], false, false, true)['config']
|
1007
1010
|
item_payload.deep_merge!({'config' => config_prompt})
|
1008
1011
|
end
|
1009
1012
|
|
@@ -1123,6 +1126,14 @@ EOT
|
|
1123
1126
|
opts.on('--releaseEIPs [true|false]', String, "Release EIPs. Default is on. Applies to Amazon only.") do |val|
|
1124
1127
|
params[:releaseEIPs] = ['true','on','1',''].include?(val.to_s.downcase)
|
1125
1128
|
end
|
1129
|
+
opts.on('--release-ips [on|off]', ['on','off'], "Release Floating IPs. Default is on. Applies to certain types only.") do |val|
|
1130
|
+
params[:releaseFloatingIps] = ['true','on','1',''].include?(val.to_s.downcase)
|
1131
|
+
params[:releaseEIPs] = params[:releaseFloatingIps] # old parameter before 6.0
|
1132
|
+
end
|
1133
|
+
opts.on('--releaseEIPs [on|off]', ['on','off'], "Alias for Release Floating IPs") do |val|
|
1134
|
+
params[:releaseFloatingIps] = ['true','on','1',''].include?(val.to_s.downcase)
|
1135
|
+
params[:releaseEIPs] = params[:releaseFloatingIps] # old parameter before 6.0
|
1136
|
+
end
|
1126
1137
|
opts.on( '-f', '--force', "Force Delete" ) do
|
1127
1138
|
params[:force] = true
|
1128
1139
|
end
|
@@ -1471,4 +1482,35 @@ EOT
|
|
1471
1482
|
out + return_color
|
1472
1483
|
end
|
1473
1484
|
|
1485
|
+
|
1486
|
+
def construct_catalog_api_params(record)
|
1487
|
+
catalog_item_type_id = record['id'].to_i
|
1488
|
+
api_params = {}
|
1489
|
+
api_params['catalogItemType'] ||= {}
|
1490
|
+
api_params['catalogItemType']['id'] = catalog_item_type_id
|
1491
|
+
# Determine instance.type value
|
1492
|
+
# the UI is injecting this parameter into the option source requests
|
1493
|
+
# it is needed to populate api option lists eg. optionTypeClouds
|
1494
|
+
# this should be fixed on the api side, so it automatically extracts this input from the config
|
1495
|
+
begin
|
1496
|
+
instance_type_code = nil
|
1497
|
+
catalog_item_type = find_by_id(:catalog_item_type, catalog_item_type_id.to_i)
|
1498
|
+
if catalog_item_type
|
1499
|
+
if catalog_item_type['type'] == 'instance'
|
1500
|
+
if catalog_item_type['config'] && catalog_item_type['config']['type']
|
1501
|
+
instance_type_code = catalog_item_type['config']['type']
|
1502
|
+
end
|
1503
|
+
end
|
1504
|
+
end
|
1505
|
+
if instance_type_code
|
1506
|
+
api_params['instance'] ||= {}
|
1507
|
+
api_params['instance']['type'] = instance_type_code
|
1508
|
+
end
|
1509
|
+
rescue ::RestClient::Exception => e
|
1510
|
+
# users may not have permission to this endpoint
|
1511
|
+
# puts "Failed to load catalog item type"
|
1512
|
+
end
|
1513
|
+
return api_params
|
1514
|
+
end
|
1515
|
+
|
1474
1516
|
end
|
@@ -902,7 +902,7 @@ class Morpheus::Cli::Tasks
|
|
902
902
|
opts.on(nil, '--no-refresh', "Do not refresh" ) do
|
903
903
|
options[:no_refresh] = true
|
904
904
|
end
|
905
|
-
|
905
|
+
build_standard_post_options(opts, options)
|
906
906
|
end
|
907
907
|
optparse.parse!(args)
|
908
908
|
if args.count != 1
|
@@ -593,7 +593,7 @@ class Morpheus::Cli::Workflows
|
|
593
593
|
opts.on(nil, '--no-refresh', "Do not refresh" ) do
|
594
594
|
options[:no_refresh] = true
|
595
595
|
end
|
596
|
-
|
596
|
+
build_standard_post_options(opts, options)
|
597
597
|
end
|
598
598
|
optparse.parse!(args)
|
599
599
|
if args.count != 1
|
@@ -123,7 +123,8 @@ module Morpheus
|
|
123
123
|
end
|
124
124
|
if password.empty?
|
125
125
|
# readline is still echoing secret with 'NUL:'' so just use $stdin on windows for now
|
126
|
-
|
126
|
+
# and some other environments? just use noecho unless running unit tests
|
127
|
+
if Morpheus::Cli.windows? || !Morpheus::Cli.testing?
|
127
128
|
print "Password: #{required_blue_prompt} "
|
128
129
|
# this should be my_terminal.stdin instead of STDIN and $stdin
|
129
130
|
password = $stdin.noecho(&:gets).chomp!
|
@@ -39,6 +39,18 @@ module Morpheus::Cli::InfrastructureHelper
|
|
39
39
|
@network_groups_interface
|
40
40
|
end
|
41
41
|
|
42
|
+
def resource_pool_groups_interface
|
43
|
+
# @api_client.resource_pool_groups
|
44
|
+
raise "#{self.class} has not defined @resource_pool_groups_interface" if @resource_pool_groups_interface.nil?
|
45
|
+
@resource_pool_groups_interface
|
46
|
+
end
|
47
|
+
|
48
|
+
def resource_pools_interface
|
49
|
+
# @api_client.resource_pool_groups
|
50
|
+
raise "#{self.class} has not defined @cloud_resource_pools_interface" if @cloud_resource_pools_interface.nil?
|
51
|
+
@cloud_resource_pools_interface
|
52
|
+
end
|
53
|
+
|
42
54
|
def network_types_interface
|
43
55
|
# @api_client.network_types
|
44
56
|
raise "#{self.class} has not defined @network_types_interface" if @network_types_interface.nil?
|
@@ -343,6 +355,86 @@ module Morpheus::Cli::InfrastructureHelper
|
|
343
355
|
end
|
344
356
|
end
|
345
357
|
|
358
|
+
def find_resource_pool_by_name_or_id(val)
|
359
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
360
|
+
return find_resource_pool_by_id(val)
|
361
|
+
else
|
362
|
+
return find_resource_pool_by_name(val)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def find_resource_pool_by_id(id)
|
367
|
+
begin
|
368
|
+
json_response = resource_pools_interface.get_without_cloud(id.to_i)
|
369
|
+
return json_response['resourcePool']
|
370
|
+
rescue RestClient::Exception => e
|
371
|
+
if e.response && e.response.code == 404
|
372
|
+
print_red_alert "Resource Pool not found by id #{id}"
|
373
|
+
return nil
|
374
|
+
else
|
375
|
+
raise e
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
def find_resource_pool_by_name(name)
|
381
|
+
json_response = resource_pools_interface.list_without_cloud({name: name.to_s})
|
382
|
+
resource_pools = json_response['resourcePools']
|
383
|
+
if resource_pools.empty?
|
384
|
+
print_red_alert "Resource Pool not found by name #{name}"
|
385
|
+
return nil
|
386
|
+
elsif resource_pools.size > 1
|
387
|
+
print_red_alert "#{resource_pools.size} resource pools found by name #{name}"
|
388
|
+
rows = resource_pools.collect do |it|
|
389
|
+
{id: it['id'], name: it['name']}
|
390
|
+
end
|
391
|
+
puts as_pretty_table(rows, [:id, :name], {color:red})
|
392
|
+
return nil
|
393
|
+
else
|
394
|
+
return resource_pools[0]
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
def find_resource_pool_group_by_name_or_id(val)
|
399
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
400
|
+
return find_resource_pool_group_by_id(val)
|
401
|
+
else
|
402
|
+
return find_resource_pool_group_by_name(val)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
def find_resource_pool_group_by_id(id)
|
407
|
+
begin
|
408
|
+
json_response = resource_pool_groups_interface.get(id.to_i)
|
409
|
+
return json_response['resourcePoolGroup']
|
410
|
+
rescue RestClient::Exception => e
|
411
|
+
if e.response && e.response.code == 404
|
412
|
+
print_red_alert "Resource Pool Group not found by id #{id}"
|
413
|
+
return nil
|
414
|
+
else
|
415
|
+
raise e
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
def find_resource_pool_group_by_name(name)
|
421
|
+
json_response = resource_pool_groups_interface.list({name: name.to_s})
|
422
|
+
resource_pool_groups = json_response['resourcePoolGroups']
|
423
|
+
if resource_pool_groups.empty?
|
424
|
+
print_red_alert "Resource Pool Group not found by name #{name}"
|
425
|
+
return nil
|
426
|
+
elsif resource_pool_groups.size > 1
|
427
|
+
print_red_alert "#{resource_pool_groups.size} resource pool groups found by name #{name}"
|
428
|
+
rows = resource_pool_groups.collect do |it|
|
429
|
+
{id: it['id'], name: it['name']}
|
430
|
+
end
|
431
|
+
puts as_pretty_table(rows, [:id, :name], {color:red})
|
432
|
+
return nil
|
433
|
+
else
|
434
|
+
return resource_pool_groups[0]
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
346
438
|
def prompt_for_network(network_id, options={}, required=true, field_name='network', field_label='Network')
|
347
439
|
# Prompt for a Network, text input that searches by name or id
|
348
440
|
network = nil
|
@@ -479,6 +571,62 @@ module Morpheus::Cli::InfrastructureHelper
|
|
479
571
|
return {success:true, data: record_ids}
|
480
572
|
end
|
481
573
|
|
574
|
+
def prompt_for_pools(params, options={}, api_client=nil, api_params={})
|
575
|
+
# Pools
|
576
|
+
pool_list = nil
|
577
|
+
pool_ids = nil
|
578
|
+
still_prompting = true
|
579
|
+
if params['pools'].nil?
|
580
|
+
still_prompting = true
|
581
|
+
while still_prompting do
|
582
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pools', 'type' => 'text', 'fieldLabel' => 'Pools', 'required' => false, 'description' => 'Pools to include, comma separated list of names or IDs.'}], options[:options])
|
583
|
+
unless v_prompt['pools'].to_s.empty?
|
584
|
+
pool_list = v_prompt['pools'].split(",").collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
585
|
+
end
|
586
|
+
pool_ids = []
|
587
|
+
bad_ids = []
|
588
|
+
if pool_list && pool_list.size > 0
|
589
|
+
pool_list.each do |it|
|
590
|
+
found_pool = nil
|
591
|
+
begin
|
592
|
+
found_pool = find_resource_pool_by_name_or_id(it)
|
593
|
+
rescue SystemExit => cmdexit
|
594
|
+
end
|
595
|
+
if found_pool
|
596
|
+
pool_ids << found_pool['id']
|
597
|
+
else
|
598
|
+
bad_ids << it
|
599
|
+
end
|
600
|
+
end
|
601
|
+
end
|
602
|
+
still_prompting = bad_ids.empty? ? false : true
|
603
|
+
end
|
604
|
+
else
|
605
|
+
pool_list = params['pools']
|
606
|
+
still_prompting = false
|
607
|
+
pool_ids = []
|
608
|
+
bad_ids = []
|
609
|
+
if pool_list && pool_list.size > 0
|
610
|
+
pool_list.each do |it|
|
611
|
+
found_pool = nil
|
612
|
+
begin
|
613
|
+
found_pool = find_resource_pool_by_name_or_id(it)
|
614
|
+
rescue SystemExit => cmdexit
|
615
|
+
end
|
616
|
+
if found_pool
|
617
|
+
pool_ids << found_pool['id']
|
618
|
+
else
|
619
|
+
bad_ids << it
|
620
|
+
end
|
621
|
+
end
|
622
|
+
end
|
623
|
+
if !bad_ids.empty?
|
624
|
+
return {success:false, msg:"Pools not found: #{bad_ids}"}
|
625
|
+
end
|
626
|
+
end
|
627
|
+
return {success:true, data: pool_ids}
|
628
|
+
end
|
629
|
+
|
482
630
|
def network_pool_server_list_column_definitions(options)
|
483
631
|
{
|
484
632
|
"ID" => 'id',
|
@@ -55,7 +55,7 @@ module Morpheus
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
def self.prompt(option_types, options={}, api_client=nil, api_params={}, no_prompt=false, paging_enabled=false, ignore_empty=false)
|
58
|
+
def self.prompt(option_types, options={}, api_client=nil, api_params={}, no_prompt=false, paging_enabled=false, ignore_empty=false, skip_sort = false)
|
59
59
|
paging_enabled = false if Morpheus::Cli.windows?
|
60
60
|
no_prompt = no_prompt || options[:no_prompt]
|
61
61
|
results = {}
|
@@ -89,12 +89,18 @@ module Morpheus
|
|
89
89
|
# puts "Options Prompt #{options}"
|
90
90
|
# Sort options by default, group, advanced
|
91
91
|
# add displayOrder if it's missing, so it doesn't end up using a random order
|
92
|
-
if !option_types.find {|it| it['displayOrder'] }
|
93
|
-
|
94
|
-
end
|
92
|
+
# if !option_types.find {|it| it['displayOrder'] && it['displayOrder'] != 0 }
|
93
|
+
# option_types.each_with_index {|it, i| it['displayOrder'] = i+1 }
|
94
|
+
# end
|
95
95
|
cur_field_group = 'default'
|
96
96
|
prompt_local_credentials = true
|
97
|
-
|
97
|
+
# reject help only options..
|
98
|
+
option_types.reject! {|it| it[:for_help_only]}
|
99
|
+
# sort options
|
100
|
+
if !skip_sort
|
101
|
+
option_types = self.sort_option_types(option_types)
|
102
|
+
end
|
103
|
+
option_types.each do |option_type|
|
98
104
|
next if option_type['localCredential'] && !prompt_local_credentials
|
99
105
|
context_map = results
|
100
106
|
value = nil
|
@@ -672,7 +678,7 @@ module Morpheus
|
|
672
678
|
# print "Perhaps you meant one of these? #{ored_list(matched_options.collect {|i|i[value_field]}, 3)}\n"
|
673
679
|
print "Try using value instead of name.\n"
|
674
680
|
print "\n"
|
675
|
-
exit 1
|
681
|
+
#exit 1
|
676
682
|
elsif matched_options.size == 1
|
677
683
|
matched_option = matched_options[0]
|
678
684
|
end
|
@@ -998,8 +1004,9 @@ module Morpheus
|
|
998
1004
|
def self.password_prompt(option_type)
|
999
1005
|
value_found = false
|
1000
1006
|
while !value_found do
|
1001
|
-
# readline is still echoing secret with 'NUL:'' so just use $stdin on windows
|
1002
|
-
|
1007
|
+
# readline is still echoing secret with 'NUL:'' so just use $stdin on windows
|
1008
|
+
# and some other environments? just use noecho unless running unit tests
|
1009
|
+
if Morpheus::Cli.windows? || !Morpheus::Cli.testing?
|
1003
1010
|
print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? (' (' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)}#{option_type['defaultValue'] ? ' ['+'************'+']' : ''}: "
|
1004
1011
|
input = $stdin.noecho(&:gets).chomp!
|
1005
1012
|
else
|
data/lib/morpheus/cli/version.rb
CHANGED
data/lib/morpheus/cli.rb
CHANGED
@@ -77,6 +77,19 @@ module Morpheus
|
|
77
77
|
Dir[File.dirname(__FILE__) + "/cli/commands/**/*.rb"].each {|file| load file }
|
78
78
|
end
|
79
79
|
|
80
|
+
# hack needed for unit tests right now
|
81
|
+
@@testing = false unless defined?(@@testing)
|
82
|
+
|
83
|
+
# hack needed for unit tests right now
|
84
|
+
def self.enable_test_mode
|
85
|
+
@@testing = true
|
86
|
+
end
|
87
|
+
|
88
|
+
# hack needed for unit tests right now
|
89
|
+
def self.testing?
|
90
|
+
defined?(@@testing) && @@testing == true
|
91
|
+
end
|
92
|
+
|
80
93
|
# require all CLI modules now (on require)
|
81
94
|
load!
|
82
95
|
|
data/test/cli/doc_test.rb
CHANGED
data/test/test_case.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: morpheus-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Estes
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2023-
|
14
|
+
date: 2023-03-02 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -280,6 +280,7 @@ files:
|
|
280
280
|
- lib/morpheus/api/network_domain_records_interface.rb
|
281
281
|
- lib/morpheus/api/network_domains_interface.rb
|
282
282
|
- lib/morpheus/api/network_edge_clusters_interface.rb
|
283
|
+
- lib/morpheus/api/network_floating_ips_interface.rb
|
283
284
|
- lib/morpheus/api/network_groups_interface.rb
|
284
285
|
- lib/morpheus/api/network_pool_ips_interface.rb
|
285
286
|
- lib/morpheus/api/network_pool_server_types_interface.rb
|
@@ -313,6 +314,7 @@ files:
|
|
313
314
|
- lib/morpheus/api/provisioning_settings_interface.rb
|
314
315
|
- lib/morpheus/api/read_interface.rb
|
315
316
|
- lib/morpheus/api/reports_interface.rb
|
317
|
+
- lib/morpheus/api/resource_pool_groups_interface.rb
|
316
318
|
- lib/morpheus/api/rest_interface.rb
|
317
319
|
- lib/morpheus/api/roles_interface.rb
|
318
320
|
- lib/morpheus/api/scale_thresholds_interface.rb
|
@@ -455,6 +457,7 @@ files:
|
|
455
457
|
- lib/morpheus/cli/commands/network_domains_command.rb
|
456
458
|
- lib/morpheus/cli/commands/network_edge_clusters_command.rb
|
457
459
|
- lib/morpheus/cli/commands/network_firewalls_command.rb
|
460
|
+
- lib/morpheus/cli/commands/network_floating_ips.rb
|
458
461
|
- lib/morpheus/cli/commands/network_groups_command.rb
|
459
462
|
- lib/morpheus/cli/commands/network_pool_server_types.rb
|
460
463
|
- lib/morpheus/cli/commands/network_pool_servers_command.rb
|
@@ -483,6 +486,7 @@ files:
|
|
483
486
|
- lib/morpheus/cli/commands/recent_activity_command.rb
|
484
487
|
- lib/morpheus/cli/commands/remote.rb
|
485
488
|
- lib/morpheus/cli/commands/reports_command.rb
|
489
|
+
- lib/morpheus/cli/commands/resource_pool_groups_command.rb
|
486
490
|
- lib/morpheus/cli/commands/rm_command.rb
|
487
491
|
- lib/morpheus/cli/commands/roles.rb
|
488
492
|
- lib/morpheus/cli/commands/scale_thresholds.rb
|