morpheus-cli 5.4.4 → 5.4.5
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/apps_interface.rb +18 -4
- data/lib/morpheus/api/instances_interface.rb +16 -2
- data/lib/morpheus/cli/commands/apps.rb +366 -47
- data/lib/morpheus/cli/commands/clusters.rb +70 -10
- data/lib/morpheus/cli/commands/dashboard_command.rb +1 -1
- data/lib/morpheus/cli/commands/execution_request_command.rb +9 -4
- data/lib/morpheus/cli/commands/file_copy_request_command.rb +2 -1
- data/lib/morpheus/cli/commands/instances.rb +311 -17
- data/lib/morpheus/cli/commands/library_layouts_command.rb +15 -0
- data/lib/morpheus/cli/commands/provisioning_licenses_command.rb +1 -1
- data/lib/morpheus/cli/mixins/execution_request_helper.rb +50 -0
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +4 -4
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +10 -4
- data/lib/morpheus/cli/option_types.rb +10 -4
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/formatters.rb +12 -0
- metadata +3 -2
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'morpheus/cli/mixins/print_helper'
|
|
2
|
+
# Mixin for Morpheus::Cli command classes
|
|
3
|
+
# Provides common methods for provisioning instances
|
|
4
|
+
module Morpheus::Cli::ExecutionRequestHelper
|
|
5
|
+
|
|
6
|
+
def self.included(klass)
|
|
7
|
+
klass.send :include, Morpheus::Cli::PrintHelper
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def api_client
|
|
11
|
+
raise "#{self.class} has not defined @api_client" if @api_client.nil?
|
|
12
|
+
@api_client
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def execution_request_interface
|
|
16
|
+
# get_interface('execution_request')
|
|
17
|
+
api_client.execution_request
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# refresh execution request until it is finished
|
|
21
|
+
# returns json response data of the last execution request when status reached 'completed' or 'failed'
|
|
22
|
+
def wait_for_execution_request(execution_request_id, options={}, print_output = true)
|
|
23
|
+
refresh_interval = 10
|
|
24
|
+
if options[:refresh_interval].to_i > 0
|
|
25
|
+
refresh_interval = options[:refresh_interval]
|
|
26
|
+
end
|
|
27
|
+
execution_request = execution_request_interface.get(execution_request_id)['executionRequest']
|
|
28
|
+
refresh_display_seconds = refresh_interval % 1.0 == 0 ? refresh_interval.to_i : refresh_interval
|
|
29
|
+
# unless options[:quiet]
|
|
30
|
+
# print cyan, "Execution request has not yet finished. Refreshing every #{refresh_display_seconds} seconds...", "\n", reset
|
|
31
|
+
# end
|
|
32
|
+
while execution_request['status'] == 'pending' || execution_request['status'] == 'new' do
|
|
33
|
+
sleep(refresh_interval)
|
|
34
|
+
execution_request = execution_request_interface.get(execution_request_id)['executionRequest']
|
|
35
|
+
end
|
|
36
|
+
if print_output && options[:quiet] != true
|
|
37
|
+
if execution_request['stdErr'].to_s.strip != '' && execution_request['stdErr'] != "stdin: is not a tty\n"
|
|
38
|
+
print_h2 "Error"
|
|
39
|
+
print execution_request['stdErr'].to_s.strip, reset, "\n"
|
|
40
|
+
end
|
|
41
|
+
if execution_request['stdOut'].to_s.strip != ''
|
|
42
|
+
print_h2 "Output"
|
|
43
|
+
print execution_request['stdOut'].to_s.strip, reset, "\n"
|
|
44
|
+
end
|
|
45
|
+
print reset, "\n"
|
|
46
|
+
end
|
|
47
|
+
return execution_request
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -1120,7 +1120,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
|
1120
1120
|
storage_type = nil
|
|
1121
1121
|
else
|
|
1122
1122
|
default_storage_type = root_storage_types.find {|t| t['value'].to_s == volume['storageType'].to_s}
|
|
1123
|
-
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => 'Root Storage Type', 'selectOptions' => root_storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.', 'defaultValue' => default_storage_type ? default_storage_type['name'] : volume['storageType']}], options[:options])
|
|
1123
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => 'Root Storage Type', 'selectOptions' => root_storage_types, 'required' => true, 'defaultFirstOption' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.', 'defaultValue' => default_storage_type ? default_storage_type['name'] : volume['storageType']}], options[:options])
|
|
1124
1124
|
storage_type_id = v_prompt[field_context]['storageType']
|
|
1125
1125
|
storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
|
|
1126
1126
|
volume['storageType'] = storage_type_id
|
|
@@ -1191,7 +1191,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
|
1191
1191
|
volume = options[:options]['volumes'][volume_index]
|
|
1192
1192
|
end
|
|
1193
1193
|
|
|
1194
|
-
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.', 'defaultValue' => volume['storageType']}], options[:options])
|
|
1194
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'defaultFirstOption' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.', 'defaultValue' => volume['storageType']}], options[:options])
|
|
1195
1195
|
storage_type_id = v_prompt[field_context]['storageType']
|
|
1196
1196
|
volume['storageType'] = storage_type_id
|
|
1197
1197
|
storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
|
|
@@ -1313,7 +1313,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
|
1313
1313
|
storage_type_id = nil
|
|
1314
1314
|
storage_type = nil
|
|
1315
1315
|
else
|
|
1316
|
-
#v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => 'Root Storage Type', 'selectOptions' => root_storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
|
|
1316
|
+
#v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => 'Root Storage Type', 'selectOptions' => root_storage_types, 'required' => true, 'defaultFirstOption' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
|
|
1317
1317
|
#storage_type_id = v_prompt[field_context]['storageType']
|
|
1318
1318
|
storage_type_id = current_root_volume['type'] || current_root_volume['storageType']
|
|
1319
1319
|
storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
|
|
@@ -1461,7 +1461,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
|
1461
1461
|
|
|
1462
1462
|
field_context = "dataVolume#{volume_index}"
|
|
1463
1463
|
|
|
1464
|
-
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
|
|
1464
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'defaultFirstOption' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
|
|
1465
1465
|
storage_type_id = v_prompt[field_context]['storageType']
|
|
1466
1466
|
storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
|
|
1467
1467
|
|
|
@@ -495,10 +495,16 @@ EOT
|
|
|
495
495
|
return
|
|
496
496
|
end
|
|
497
497
|
json_response = rest_interface.create(parent_id, payload)
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
498
|
+
if json_response['success']
|
|
499
|
+
render_response(json_response, options, rest_object_key) do
|
|
500
|
+
record = json_response[rest_object_key]
|
|
501
|
+
print_green_success "Added #{rest_label.downcase} #{record['name'] || record['id']}"
|
|
502
|
+
return _get(parent_id, record["id"], {}, options)
|
|
503
|
+
end
|
|
504
|
+
else
|
|
505
|
+
print red
|
|
506
|
+
print json_response['msg']
|
|
507
|
+
print "\n"
|
|
502
508
|
end
|
|
503
509
|
return 0, nil
|
|
504
510
|
end
|
|
@@ -405,7 +405,7 @@ module Morpheus
|
|
|
405
405
|
select_options = option_type['optionSource'].call(api_client, api_params || {})
|
|
406
406
|
elsif option_type['optionSource'] == 'list'
|
|
407
407
|
# /api/options/list is a special action for custom OptionTypeLists, just need to pass the optionTypeId parameter
|
|
408
|
-
select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, api_params || {}.merge({'optionTypeId' => option_type['id']}))
|
|
408
|
+
select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, (api_params || {}).merge({'optionTypeId' => option_type['id']}))
|
|
409
409
|
else
|
|
410
410
|
# remote optionSource aka /api/options/$optionSource?
|
|
411
411
|
select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, api_params || {})
|
|
@@ -457,6 +457,12 @@ module Morpheus
|
|
|
457
457
|
end
|
|
458
458
|
end
|
|
459
459
|
end
|
|
460
|
+
# default to the first option
|
|
461
|
+
if !value_found && default_value.nil? && option_type['defaultFirstOption'] && select_options && select_options[0]
|
|
462
|
+
# default_value = select_options[0][value_field]
|
|
463
|
+
# nicer to display name instead, it will match and replace with value
|
|
464
|
+
default_value = select_options[0]['name'] ? select_options[0]['name'] : select_options[0][value_field]
|
|
465
|
+
end
|
|
460
466
|
|
|
461
467
|
if no_prompt
|
|
462
468
|
if !value_found
|
|
@@ -822,7 +828,7 @@ module Morpheus
|
|
|
822
828
|
def self.password_prompt(option_type)
|
|
823
829
|
value_found = false
|
|
824
830
|
while !value_found do
|
|
825
|
-
print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? (' (' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)}#{option_type['defaultValue'] ? ' ['+
|
|
831
|
+
print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? (' (' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)}#{option_type['defaultValue'] ? ' ['+'************'+']' : ''}: "
|
|
826
832
|
input = $stdin.noecho(&:gets).chomp!
|
|
827
833
|
value = input
|
|
828
834
|
print "\n"
|
|
@@ -999,7 +1005,7 @@ module Morpheus
|
|
|
999
1005
|
select_options = option_type['optionSource'].call(api_client, api_params || {})
|
|
1000
1006
|
elsif option_type['optionSource'] == 'list'
|
|
1001
1007
|
# /api/options/list is a special action for custom OptionTypeLists, just need to pass the optionTypeId parameter
|
|
1002
|
-
select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, api_params || {}.merge({'optionTypeId' => option_type['id']}))
|
|
1008
|
+
select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, (api_params || {}).merge({'optionTypeId' => option_type['id']}))
|
|
1003
1009
|
else
|
|
1004
1010
|
# remote optionSource aka /api/options/$optionSource?
|
|
1005
1011
|
select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, api_params || {})
|
|
@@ -1029,7 +1035,7 @@ module Morpheus
|
|
|
1029
1035
|
|
|
1030
1036
|
|
|
1031
1037
|
def self.load_source_options(source,sourceType,api_client,params)
|
|
1032
|
-
api_client.options.options_for_source("#{sourceType ? "#{sourceType}/" : ''}#{source}",params)['data']
|
|
1038
|
+
api_client.options.options_for_source("#{sourceType ? "#{sourceType}/" : ''}#{source}", params)['data']
|
|
1033
1039
|
end
|
|
1034
1040
|
|
|
1035
1041
|
def self.format_select_options_help(opt, select_options = [], paging = nil)
|
data/lib/morpheus/cli/version.rb
CHANGED
data/lib/morpheus/formatters.rb
CHANGED
|
@@ -476,3 +476,15 @@ end
|
|
|
476
476
|
def a_or_an(v)
|
|
477
477
|
v.to_s =~ /^[aeiou]/i ? "an" : "a"
|
|
478
478
|
end
|
|
479
|
+
|
|
480
|
+
def format_ok_status(status)
|
|
481
|
+
color = cyan
|
|
482
|
+
if ['ok'].include? status
|
|
483
|
+
color = green
|
|
484
|
+
elsif ['error'].include? status
|
|
485
|
+
color = red
|
|
486
|
+
elsif ['warning'].include? status
|
|
487
|
+
color = yellow
|
|
488
|
+
end
|
|
489
|
+
"#{color}#{status.to_s.upcase}#{cyan}"
|
|
490
|
+
end
|
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: 5.4.
|
|
4
|
+
version: 5.4.5
|
|
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: 2022-
|
|
14
|
+
date: 2022-04-14 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: bundler
|
|
@@ -498,6 +498,7 @@ files:
|
|
|
498
498
|
- lib/morpheus/cli/mixins/accounts_helper.rb
|
|
499
499
|
- lib/morpheus/cli/mixins/backups_helper.rb
|
|
500
500
|
- lib/morpheus/cli/mixins/deployments_helper.rb
|
|
501
|
+
- lib/morpheus/cli/mixins/execution_request_helper.rb
|
|
501
502
|
- lib/morpheus/cli/mixins/infrastructure_helper.rb
|
|
502
503
|
- lib/morpheus/cli/mixins/library_helper.rb
|
|
503
504
|
- lib/morpheus/cli/mixins/load_balancers_helper.rb
|