morpheus-cli 3.6.8 → 3.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/morpheus/api/account_groups_interface.rb +2 -2
- data/lib/morpheus/api/accounts_interface.rb +4 -7
- data/lib/morpheus/api/api_client.rb +207 -70
- data/lib/morpheus/api/app_templates_interface.rb +7 -28
- data/lib/morpheus/api/apps_interface.rb +14 -21
- data/lib/morpheus/api/archive_buckets_interface.rb +2 -2
- data/lib/morpheus/api/archive_files_interface.rb +6 -6
- data/lib/morpheus/api/auth_interface.rb +14 -1
- data/lib/morpheus/api/blueprints_interface.rb +9 -16
- data/lib/morpheus/api/cloud_datastores_interface.rb +1 -1
- data/lib/morpheus/api/cloud_policies_interface.rb +1 -1
- data/lib/morpheus/api/clouds_interface.rb +18 -21
- data/lib/morpheus/api/cypher_interface.rb +19 -28
- data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
- data/lib/morpheus/api/group_policies_interface.rb +1 -1
- data/lib/morpheus/api/groups_interface.rb +4 -4
- data/lib/morpheus/api/image_builder_boot_scripts_interface.rb +1 -1
- data/lib/morpheus/api/image_builder_image_builds_interface.rb +2 -2
- data/lib/morpheus/api/image_builder_preseed_scripts_interface.rb +1 -1
- data/lib/morpheus/api/instances_interface.rb +17 -23
- data/lib/morpheus/api/logs_interface.rb +7 -10
- data/lib/morpheus/api/network_domains_interface.rb +1 -1
- data/lib/morpheus/api/network_groups_interface.rb +1 -1
- data/lib/morpheus/api/network_pool_servers_interface.rb +1 -1
- data/lib/morpheus/api/network_pools_interface.rb +1 -1
- data/lib/morpheus/api/network_proxies_interface.rb +1 -1
- data/lib/morpheus/api/network_services_interface.rb +1 -1
- data/lib/morpheus/api/networks_interface.rb +1 -1
- data/lib/morpheus/api/old_cypher_interface.rb +55 -0
- data/lib/morpheus/api/packages_interface.rb +1 -1
- data/lib/morpheus/api/policies_interface.rb +1 -1
- data/lib/morpheus/api/setup_interface.rb +1 -1
- data/lib/morpheus/api/storage_providers_interface.rb +1 -1
- data/lib/morpheus/api/whoami_interface.rb +1 -1
- data/lib/morpheus/benchmarking.rb +277 -0
- data/lib/morpheus/cli.rb +6 -22
- data/lib/morpheus/cli/access_token_command.rb +172 -0
- data/lib/morpheus/cli/accounts.rb +5 -0
- data/lib/morpheus/cli/apps.rb +93 -37
- data/lib/morpheus/cli/archives_command.rb +0 -2
- data/lib/morpheus/cli/auth_command.rb +112 -0
- data/lib/morpheus/cli/blueprints_command.rb +50 -13
- data/lib/morpheus/cli/change_password_command.rb +148 -0
- data/lib/morpheus/cli/cli_command.rb +173 -49
- data/lib/morpheus/cli/clouds.rb +15 -5
- data/lib/morpheus/cli/command_error.rb +7 -1
- data/lib/morpheus/cli/{alias_command.rb → commands/standard/alias_command.rb} +79 -51
- data/lib/morpheus/cli/commands/standard/benchmark_command.rb +399 -0
- data/lib/morpheus/cli/commands/standard/coloring_command.rb +60 -0
- data/lib/morpheus/cli/{curl_command.rb → commands/standard/curl_command.rb} +0 -7
- data/lib/morpheus/cli/commands/standard/debug_command.rb +61 -0
- data/lib/morpheus/cli/{echo_command.rb → commands/standard/echo_command.rb} +1 -1
- data/lib/morpheus/cli/{edit_profile_command.rb → commands/standard/edit_profile_command.rb} +0 -0
- data/lib/morpheus/cli/{edit_rc_command.rb → commands/standard/edit_rc_command.rb} +0 -0
- data/lib/morpheus/cli/commands/standard/get_prompt_command.rb +39 -0
- data/lib/morpheus/cli/commands/standard/history_command.rb +76 -0
- data/lib/morpheus/cli/{log_level_command.rb → commands/standard/log_level_command.rb} +1 -1
- data/lib/morpheus/cli/{man_command.rb → commands/standard/man_command.rb} +2 -2
- data/lib/morpheus/cli/commands/standard/rm_command.rb +14 -0
- data/lib/morpheus/cli/commands/standard/set_prompt_command.rb +54 -0
- data/lib/morpheus/cli/{sleep_command.rb → commands/standard/sleep_command.rb} +0 -0
- data/lib/morpheus/cli/{source_command.rb → commands/standard/source_command.rb} +0 -0
- data/lib/morpheus/cli/{ssl_verification_command.rb → commands/standard/ssl_verification_command.rb} +1 -1
- data/lib/morpheus/cli/commands/standard/tee_command.rb +14 -0
- data/lib/morpheus/cli/{version_command.rb → commands/standard/version_command.rb} +0 -0
- data/lib/morpheus/cli/credentials.rb +276 -87
- data/lib/morpheus/cli/cypher_command.rb +333 -214
- data/lib/morpheus/cli/error_handler.rb +12 -2
- data/lib/morpheus/cli/groups.rb +44 -20
- data/lib/morpheus/cli/hosts.rb +39 -16
- data/lib/morpheus/cli/instances.rb +114 -62
- data/lib/morpheus/cli/login.rb +74 -21
- data/lib/morpheus/cli/logout.rb +3 -4
- data/lib/morpheus/cli/mixins/accounts_helper.rb +50 -18
- data/lib/morpheus/cli/mixins/print_helper.rb +207 -42
- data/lib/morpheus/cli/old_cypher_command.rb +414 -0
- data/lib/morpheus/cli/option_parser.rb +6 -1
- data/lib/morpheus/cli/processes_command.rb +3 -0
- data/lib/morpheus/cli/remote.rb +11 -17
- data/lib/morpheus/cli/roles.rb +17 -17
- data/lib/morpheus/cli/security_groups.rb +47 -17
- data/lib/morpheus/cli/shell.rb +139 -79
- data/lib/morpheus/cli/tenants_command.rb +353 -0
- data/lib/morpheus/cli/users.rb +26 -18
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/whoami.rb +14 -10
- data/lib/morpheus/formatters.rb +4 -4
- data/lib/morpheus/logging.rb +16 -8
- data/lib/morpheus/terminal.rb +63 -34
- metadata +28 -15
- data/lib/morpheus/cli/coloring_command.rb +0 -45
- data/lib/morpheus/cli/set_prompt_command.rb +0 -51
data/lib/morpheus/cli/remote.rb
CHANGED
|
@@ -64,7 +64,7 @@ EOT
|
|
|
64
64
|
return 0
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
print_h1 "Morpheus Appliances"
|
|
67
|
+
print_h1 "Morpheus Appliances", [], options
|
|
68
68
|
if appliances.empty?
|
|
69
69
|
print yellow
|
|
70
70
|
puts "You have no appliances configured. See the `remote add` command."
|
|
@@ -494,9 +494,9 @@ EOT
|
|
|
494
494
|
|
|
495
495
|
if appliance[:active]
|
|
496
496
|
# print_h1 "Current Remote Appliance: #{appliance[:name]}"
|
|
497
|
-
print_h1 "Remote Appliance: #{appliance[:name]}"
|
|
497
|
+
print_h1 "Remote Appliance: #{appliance[:name]}", [], options
|
|
498
498
|
else
|
|
499
|
-
print_h1 "Remote Appliance: #{appliance[:name]}"
|
|
499
|
+
print_h1 "Remote Appliance: #{appliance[:name]}", [], options
|
|
500
500
|
end
|
|
501
501
|
print cyan
|
|
502
502
|
description_cols = {
|
|
@@ -560,7 +560,7 @@ EOT
|
|
|
560
560
|
|
|
561
561
|
# ok, delete it
|
|
562
562
|
::Morpheus::Cli::Remote.delete_remote(appliance_name)
|
|
563
|
-
|
|
563
|
+
|
|
564
564
|
# return result
|
|
565
565
|
if options[:quiet]
|
|
566
566
|
return 0, nil
|
|
@@ -667,7 +667,7 @@ EOT
|
|
|
667
667
|
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
|
668
668
|
opts.banner = subcommand_usage()
|
|
669
669
|
build_common_options(opts, options, [])
|
|
670
|
-
opts.footer = "
|
|
670
|
+
opts.footer = "Print the name of the current remote appliance"
|
|
671
671
|
end
|
|
672
672
|
optparse.parse!(args)
|
|
673
673
|
|
|
@@ -735,7 +735,7 @@ EOT
|
|
|
735
735
|
# end
|
|
736
736
|
return false
|
|
737
737
|
else
|
|
738
|
-
print_h1 "Morpheus Appliance Setup"
|
|
738
|
+
print_h1 "Morpheus Appliance Setup", [], options
|
|
739
739
|
|
|
740
740
|
puts "It looks like you're the first one here."
|
|
741
741
|
puts "Let's initialize your remote appliance at #{@appliance_url}"
|
|
@@ -743,7 +743,7 @@ EOT
|
|
|
743
743
|
|
|
744
744
|
|
|
745
745
|
# Master Account
|
|
746
|
-
print_h2 "Create Master Account"
|
|
746
|
+
print_h2 "Create Master Account", options
|
|
747
747
|
account_option_types = [
|
|
748
748
|
{'fieldName' => 'accountName', 'fieldLabel' => 'Master Account Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
|
749
749
|
]
|
|
@@ -751,7 +751,7 @@ EOT
|
|
|
751
751
|
payload.merge!(v_prompt)
|
|
752
752
|
|
|
753
753
|
# Master User
|
|
754
|
-
print_h2 "Create Master User"
|
|
754
|
+
print_h2 "Create Master User", options
|
|
755
755
|
user_option_types = [
|
|
756
756
|
{'fieldName' => 'firstName', 'fieldLabel' => 'First Name', 'type' => 'text', 'required' => false, 'displayOrder' => 1},
|
|
757
757
|
{'fieldName' => 'lastName', 'fieldLabel' => 'Last Name', 'type' => 'text', 'required' => false, 'displayOrder' => 2},
|
|
@@ -774,7 +774,7 @@ EOT
|
|
|
774
774
|
payload.merge!(v_prompt)
|
|
775
775
|
|
|
776
776
|
# Extra settings
|
|
777
|
-
print_h2 "Initial Setup"
|
|
777
|
+
print_h2 "Initial Setup", options
|
|
778
778
|
extra_option_types = [
|
|
779
779
|
{'fieldName' => 'applianceName', 'fieldLabel' => 'Appliance Name', 'type' => 'text', 'required' => true, 'defaultValue' => nil},
|
|
780
780
|
{'fieldName' => 'applianceUrl', 'fieldLabel' => 'Appliance URL', 'type' => 'text', 'required' => true, 'defaultValue' => appliance_status_json['applianceUrl']},
|
|
@@ -847,10 +847,8 @@ EOT
|
|
|
847
847
|
out << "#{green}#{status_str.upcase}#{return_color}"
|
|
848
848
|
elsif status_str == "unreachable"
|
|
849
849
|
out << "#{red}#{status_str.upcase}#{return_color}"
|
|
850
|
-
elsif
|
|
851
|
-
out << "#{red}#{status_str.upcase}#{return_color}"
|
|
852
|
-
# elsif status_str == "unknown"
|
|
853
|
-
# out << "#{yellow}#{status_str}#{return_color}"
|
|
850
|
+
elsif ['error', 'net-error', 'ssl-error', 'http-timeout', 'unreachable']
|
|
851
|
+
out << "#{red}#{status_str.upcase.gsub('-',' ')}#{return_color}"
|
|
854
852
|
elsif status_str == "fresh"
|
|
855
853
|
# cold appliance, needs setup
|
|
856
854
|
out << "#{magenta}#{status_str.upcase}#{return_color}"
|
|
@@ -887,10 +885,6 @@ EOT
|
|
|
887
885
|
# Current User
|
|
888
886
|
#
|
|
889
887
|
username = app_map[:username]
|
|
890
|
-
# creds = app_map[:access_token]
|
|
891
|
-
#creds = Morpheus::Cli::Credentials.new(app_map[:name], app_map[:host]).load_saved_credentials()
|
|
892
|
-
|
|
893
|
-
|
|
894
888
|
|
|
895
889
|
if app_map[:status] == 'ready'
|
|
896
890
|
|
data/lib/morpheus/cli/roles.rb
CHANGED
|
@@ -50,7 +50,7 @@ class Morpheus::Cli::Roles
|
|
|
50
50
|
params.merge!(parse_list_options(options))
|
|
51
51
|
|
|
52
52
|
if options[:dry_run]
|
|
53
|
-
print_dry_run @roles_interface.dry.list(account_id, params)
|
|
53
|
+
print_dry_run @roles_interface.dry.list(account_id, params), options
|
|
54
54
|
return
|
|
55
55
|
end
|
|
56
56
|
load_whoami()
|
|
@@ -69,11 +69,11 @@ class Morpheus::Cli::Roles
|
|
|
69
69
|
title = "Morpheus Roles"
|
|
70
70
|
subtitles = []
|
|
71
71
|
subtitles += parse_list_subtitles(options)
|
|
72
|
-
print_h1 title, subtitles
|
|
72
|
+
print_h1 title, subtitles, options
|
|
73
73
|
if roles.empty?
|
|
74
74
|
print cyan,"No roles found.",reset,"\n"
|
|
75
75
|
else
|
|
76
|
-
print_roles_table(roles, {is_master_account: @is_master_account})
|
|
76
|
+
print_roles_table(roles, options.merge({is_master_account: @is_master_account}))
|
|
77
77
|
print_results_pagination(json_response)
|
|
78
78
|
end
|
|
79
79
|
print reset,"\n"
|
|
@@ -164,7 +164,7 @@ class Morpheus::Cli::Roles
|
|
|
164
164
|
end
|
|
165
165
|
|
|
166
166
|
print cyan
|
|
167
|
-
print_h1 "Role Details"
|
|
167
|
+
print_h1 "Role Details", options
|
|
168
168
|
print cyan
|
|
169
169
|
description_cols = {
|
|
170
170
|
"ID" => 'id',
|
|
@@ -180,16 +180,16 @@ class Morpheus::Cli::Roles
|
|
|
180
180
|
}
|
|
181
181
|
print_description_list(description_cols, role)
|
|
182
182
|
|
|
183
|
-
print_h2 "Role Instance Limits"
|
|
184
|
-
print cyan
|
|
185
|
-
print_description_list({
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}, role['instanceLimits'])
|
|
183
|
+
# print_h2 "Role Instance Limits", options
|
|
184
|
+
# print cyan
|
|
185
|
+
# print_description_list({
|
|
186
|
+
# "Max Storage" => lambda {|it| (it && it['maxStorage'].to_i != 0) ? Filesize.from("#{it['maxStorage']} B").pretty : "no limit" },
|
|
187
|
+
# "Max Memory" => lambda {|it| (it && it['maxMemory'].to_i != 0) ? Filesize.from("#{it['maxMemory']} B").pretty : "no limit" },
|
|
188
|
+
# "CPU Count" => lambda {|it| (it && it['maxCpu'].to_i != 0) ? it['maxCpu'] : "no limit" }
|
|
189
|
+
# }, role['instanceLimits'])
|
|
190
190
|
|
|
191
|
-
print_h2 "Feature Access"
|
|
192
|
-
print cyan
|
|
191
|
+
# print_h2 "Feature Access", options
|
|
192
|
+
# print cyan
|
|
193
193
|
|
|
194
194
|
if options[:include_feature_access]
|
|
195
195
|
rows = json_response['featurePermissions'].collect do |it|
|
|
@@ -204,7 +204,7 @@ class Morpheus::Cli::Roles
|
|
|
204
204
|
puts "Use --feature-access to list feature access"
|
|
205
205
|
end
|
|
206
206
|
|
|
207
|
-
print_h2 "Group Access"
|
|
207
|
+
print_h2 "Group Access", options
|
|
208
208
|
print cyan
|
|
209
209
|
puts "Global Group Access: #{get_access_string(json_response['globalSiteAccess'])}\n\n"
|
|
210
210
|
if json_response['globalSiteAccess'] == 'custom'
|
|
@@ -221,7 +221,7 @@ class Morpheus::Cli::Roles
|
|
|
221
221
|
end
|
|
222
222
|
end
|
|
223
223
|
|
|
224
|
-
print_h2 "Cloud Access"
|
|
224
|
+
print_h2 "Cloud Access", options
|
|
225
225
|
print cyan
|
|
226
226
|
puts "Global Cloud Access: #{get_access_string(json_response['globalZoneAccess'])}\n\n"
|
|
227
227
|
if json_response['globalZoneAccess'] == 'custom'
|
|
@@ -238,7 +238,7 @@ class Morpheus::Cli::Roles
|
|
|
238
238
|
end
|
|
239
239
|
end
|
|
240
240
|
|
|
241
|
-
print_h2 "Instance Type Access"
|
|
241
|
+
print_h2 "Instance Type Access", options
|
|
242
242
|
print cyan
|
|
243
243
|
puts "Global Instance Type Access: #{get_access_string(json_response['globalInstanceTypeAccess'])}\n\n"
|
|
244
244
|
if json_response['globalInstanceTypeAccess'] == 'custom'
|
|
@@ -257,7 +257,7 @@ class Morpheus::Cli::Roles
|
|
|
257
257
|
|
|
258
258
|
blueprint_global_access = json_response['globalAppTemplateAccess'] || json_response['globalBlueprintAccess']
|
|
259
259
|
blueprint_permissions = json_response['appTemplatePermissions'] || json_response['blueprintPermissions'] || []
|
|
260
|
-
print_h2 "Blueprint Access"
|
|
260
|
+
print_h2 "Blueprint Access", options
|
|
261
261
|
print cyan
|
|
262
262
|
puts "Global Blueprint Access: #{get_access_string(json_response['globalAppTemplateAccess'])}\n\n"
|
|
263
263
|
if blueprint_global_access == 'custom'
|
|
@@ -27,41 +27,71 @@ class Morpheus::Cli::SecurityGroups
|
|
|
27
27
|
options = {}
|
|
28
28
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
29
29
|
opts.banner = subcommand_usage()
|
|
30
|
-
build_common_options(opts, options, [:json, :dry_run])
|
|
30
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
|
31
31
|
end
|
|
32
32
|
optparse.parse!(args)
|
|
33
33
|
connect(options)
|
|
34
34
|
begin
|
|
35
35
|
params = {}
|
|
36
|
+
params.merge!(parse_list_options(options))
|
|
36
37
|
if options[:dry_run]
|
|
37
38
|
print_dry_run @security_groups_interface.dry.list(params)
|
|
38
39
|
return
|
|
39
40
|
end
|
|
40
41
|
json_response = @security_groups_interface.list(params)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
|
|
43
|
+
render_result = render_with_format(json_response, options, 'securityGroups')
|
|
44
|
+
return 0 if render_result
|
|
45
|
+
|
|
46
|
+
title = "Morpheus Security Groups"
|
|
47
|
+
subtitles = []
|
|
48
|
+
subtitles += parse_list_subtitles(options)
|
|
49
|
+
print_h1 title, subtitles
|
|
50
|
+
|
|
46
51
|
security_groups = json_response['securityGroups']
|
|
47
|
-
|
|
52
|
+
|
|
48
53
|
if security_groups.empty?
|
|
49
|
-
print yellow,"No
|
|
54
|
+
print yellow,"No security groups found.",reset,"\n"
|
|
50
55
|
else
|
|
51
56
|
active_id = @active_security_group[@appliance_name.to_sym]
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
# table_color = options[:color] || cyan
|
|
58
|
+
# rows = security_groups.collect do |security_group|
|
|
59
|
+
# {
|
|
60
|
+
# id: security_group['id'].to_s + ((security_group['id'] == active_id.to_i) ? " (active)" : ""),
|
|
61
|
+
# name: security_group['name'],
|
|
62
|
+
# description: security_group['description']
|
|
63
|
+
# }
|
|
64
|
+
# end
|
|
65
|
+
|
|
66
|
+
# columns = [
|
|
67
|
+
# :id,
|
|
68
|
+
# :name,
|
|
69
|
+
# :description,
|
|
70
|
+
# # :ports,
|
|
71
|
+
# # :status,
|
|
72
|
+
# ]
|
|
73
|
+
columns = {
|
|
74
|
+
"ID" => 'id',
|
|
75
|
+
"NAME" => 'name',
|
|
76
|
+
"DESCRIPTION" => 'description',
|
|
77
|
+
# need more to show here
|
|
78
|
+
}
|
|
79
|
+
# custom pretty table columns ...
|
|
80
|
+
if options[:include_fields]
|
|
81
|
+
columns = options[:include_fields]
|
|
58
82
|
end
|
|
59
|
-
|
|
60
|
-
|
|
83
|
+
print as_pretty_table(security_groups, columns, options)
|
|
84
|
+
print reset
|
|
85
|
+
if json_response['meta']
|
|
86
|
+
print_results_pagination(json_response, {:label => "security group", :n_label => "security groups"})
|
|
87
|
+
else
|
|
88
|
+
print_results_pagination({'meta'=>{'total'=>(json_response['securityGroupCount'] ? json_response['securityGroupCount'] : security_groups.size),'size'=>security_groups.size,'max'=>(params['max']||25),'offset'=>(params['offset']||0)}}, {:label => "security group", :n_label => "security groups"})
|
|
61
89
|
end
|
|
90
|
+
# print reset
|
|
62
91
|
end
|
|
63
92
|
print reset,"\n"
|
|
64
|
-
|
|
93
|
+
return 0
|
|
94
|
+
rescue RestClient::Exception => e
|
|
65
95
|
print_rest_exception(e, options)
|
|
66
96
|
exit 1
|
|
67
97
|
end
|
data/lib/morpheus/cli/shell.rb
CHANGED
|
@@ -10,6 +10,8 @@ require 'morpheus/cli/cli_command'
|
|
|
10
10
|
require 'morpheus/cli/error_handler'
|
|
11
11
|
require 'morpheus/cli/expression_parser'
|
|
12
12
|
require 'morpheus/terminal'
|
|
13
|
+
require 'morpheus/logging'
|
|
14
|
+
require 'morpheus/benchmarking'
|
|
13
15
|
|
|
14
16
|
#class Morpheus::Cli::Shell < Morpheus::Terminal
|
|
15
17
|
class Morpheus::Cli::Shell
|
|
@@ -88,7 +90,7 @@ class Morpheus::Cli::Shell
|
|
|
88
90
|
|
|
89
91
|
def recalculate_auto_complete_commands
|
|
90
92
|
@morpheus_commands = Morpheus::Cli::CliRegistry.all.keys.reject {|k| [:shell].include?(k) }
|
|
91
|
-
@shell_commands = [:clear, :history, :
|
|
93
|
+
@shell_commands = [:clear, :history, :reload!, :help, :exit]
|
|
92
94
|
@alias_commands = Morpheus::Cli::CliRegistry.all_aliases.keys
|
|
93
95
|
@exploded_commands = []
|
|
94
96
|
Morpheus::Cli::CliRegistry.all.each do |cmd, klass|
|
|
@@ -126,7 +128,7 @@ class Morpheus::Cli::Shell
|
|
|
126
128
|
@@insecure = true
|
|
127
129
|
Morpheus::RestClient.enable_ssl_verification = false
|
|
128
130
|
end
|
|
129
|
-
opts.on('-Z','--incognito', "Incognito mode. Use a temporary shell
|
|
131
|
+
opts.on('-Z','--incognito', "Incognito mode. Use a temporary shell. Remotes are loaded without without saved credentials or history logging.") do
|
|
130
132
|
@incognito_mode = true
|
|
131
133
|
#@norc = true # perhaps?
|
|
132
134
|
tmpdir = ENV['MORPHEUS_CLI_TMPDIR'] || ENV['TMPDIR'] || ENV['TMP']
|
|
@@ -167,11 +169,15 @@ class Morpheus::Cli::Shell
|
|
|
167
169
|
opts.on('-C','--nocolor', "Disable ANSI coloring") do
|
|
168
170
|
Term::ANSIColor::coloring = false
|
|
169
171
|
end
|
|
170
|
-
opts.on('-V','--debug', "Print extra output for debugging.") do
|
|
172
|
+
opts.on('-V','--debug', "Print extra output for debugging.") do
|
|
171
173
|
Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG)
|
|
172
174
|
::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
|
|
173
175
|
end
|
|
174
|
-
opts.on(
|
|
176
|
+
opts.on('-B','--benchmark', "Print benchmark time after each command is finished, including shell itself." ) do
|
|
177
|
+
Morpheus::Benchmarking.enabled = true
|
|
178
|
+
my_terminal.benchmarking = Morpheus::Benchmarking.enabled
|
|
179
|
+
end
|
|
180
|
+
opts.on( '-h', '--help', "Print this help" ) do
|
|
175
181
|
puts opts
|
|
176
182
|
exit
|
|
177
183
|
end
|
|
@@ -235,33 +241,12 @@ class Morpheus::Cli::Shell
|
|
|
235
241
|
return result
|
|
236
242
|
end
|
|
237
243
|
|
|
238
|
-
#
|
|
239
|
-
#
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if result.is_a?(Array) # exit_code, err
|
|
243
|
-
exit_code = result[0].to_i
|
|
244
|
-
err = result[1]
|
|
245
|
-
elsif result == nil || result == true || result == 0
|
|
246
|
-
exit_code = 0
|
|
247
|
-
elsif result == false
|
|
248
|
-
exit_code = 1
|
|
249
|
-
# elsif result.is_a?(Integer)
|
|
250
|
-
# exit_code = result.to_i
|
|
251
|
-
else
|
|
252
|
-
exit_code = result.to_i
|
|
253
|
-
end
|
|
254
|
-
# return exit_code, err
|
|
255
|
-
return exit_code
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
# same as Terminal instance
|
|
244
|
+
# execute the input as an expression.
|
|
245
|
+
# provides support for operators '(', ')', '&&', '||', ';'
|
|
246
|
+
# logs entire input as one command in shell history
|
|
247
|
+
# logging is skipped for certain commands: exit, !, !!
|
|
259
248
|
def execute(input)
|
|
260
|
-
# args = Shellwords.shellsplit(input)
|
|
261
|
-
#cmd = args.shift
|
|
262
|
-
#execute_commands(input)
|
|
263
249
|
result = execute_commands_as_expression(input)
|
|
264
|
-
# skip logging of exit and !cmd
|
|
265
250
|
unless input.strip.empty? || (["exit", "history"].include?(input.strip)) || input.strip[0].to_s.chr == "!"
|
|
266
251
|
log_history_command(input.strip)
|
|
267
252
|
end
|
|
@@ -302,12 +287,14 @@ class Morpheus::Cli::Shell
|
|
|
302
287
|
if flow_cmd == '&&'
|
|
303
288
|
# AND operator
|
|
304
289
|
current_operator = flow_cmd
|
|
305
|
-
|
|
290
|
+
exit_code, cmd_err = parse_command_result(previous_command_result)
|
|
291
|
+
if exit_code != 0
|
|
306
292
|
still_executing = false
|
|
307
293
|
end
|
|
308
294
|
elsif flow_cmd == '||' # or with previous command
|
|
309
295
|
current_operator = flow_cmd
|
|
310
|
-
|
|
296
|
+
exit_code, err = parse_command_result(previous_command_result)
|
|
297
|
+
if exit_code == 0
|
|
311
298
|
still_executing = false
|
|
312
299
|
end
|
|
313
300
|
elsif flow_cmd == '|' # or with previous command
|
|
@@ -350,9 +337,6 @@ class Morpheus::Cli::Shell
|
|
|
350
337
|
#exit 0
|
|
351
338
|
elsif input == 'help'
|
|
352
339
|
|
|
353
|
-
#print_h1 "Morpheus Shell Help", [], white
|
|
354
|
-
#print "\n"
|
|
355
|
-
|
|
356
340
|
puts "You are in a morpheus client shell."
|
|
357
341
|
puts "See the available commands below."
|
|
358
342
|
|
|
@@ -390,37 +374,37 @@ class Morpheus::Cli::Shell
|
|
|
390
374
|
# Morpheus::Logging::DarkPrinter.puts "\nInterrupt. waking up from sleep early"
|
|
391
375
|
# end
|
|
392
376
|
# return 0
|
|
393
|
-
elsif input =~ /^history/
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
377
|
+
# elsif input =~ /^history/
|
|
378
|
+
# n_commands = input.sub(/^history\s?/, '').sub(/\-n\s?/, '')
|
|
379
|
+
# n_commands = n_commands.empty? ? 25 : n_commands.to_i
|
|
380
|
+
# cmd_numbers = @history.keys.last(n_commands)
|
|
381
|
+
# if cmd_numbers.size == 1
|
|
382
|
+
# puts "Last command"
|
|
383
|
+
# else
|
|
384
|
+
# puts "Last #{cmd_numbers.size} commands"
|
|
385
|
+
# end
|
|
386
|
+
# cmd_numbers.each do |cmd_number|
|
|
387
|
+
# cmd = @history[cmd_number]
|
|
388
|
+
# puts "#{cmd_number.to_s.rjust(3, ' ')} #{cmd}"
|
|
389
|
+
# end
|
|
390
|
+
# last_cmd = cmd_numbers.last ? @history[cmd_numbers.last] : nil
|
|
391
|
+
# if input != last_cmd # no consecutive
|
|
392
|
+
# log_history_command(input)
|
|
393
|
+
# end
|
|
394
|
+
# return 0
|
|
411
395
|
elsif input == 'clear'
|
|
412
396
|
print "\e[H\e[2J"
|
|
413
397
|
return 0
|
|
414
|
-
elsif input == 'flush-history' || input == 'flush_history'
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
398
|
+
# elsif input == 'flush-history' || input == 'flush_history'
|
|
399
|
+
# file_path = history_file_path
|
|
400
|
+
# if File.exists?(file_path)
|
|
401
|
+
# File.truncate(file_path, 0)
|
|
402
|
+
# end
|
|
403
|
+
# @history = {}
|
|
404
|
+
# @last_command_number = 0
|
|
405
|
+
# @history_logger = load_history_logger
|
|
406
|
+
# puts "history cleared!"
|
|
407
|
+
# return 0
|
|
424
408
|
# elsif input == "edit rc"
|
|
425
409
|
# fn = Morpheus::Cli::DotFile.morpheusrc_filename
|
|
426
410
|
# editor = ENV['EDITOR'] # || 'nano'
|
|
@@ -511,16 +495,17 @@ class Morpheus::Cli::Shell
|
|
|
511
495
|
Morpheus::RestClient.enable_ssl_verification = false
|
|
512
496
|
return 0
|
|
513
497
|
|
|
514
|
-
# use log-level [debug|info]
|
|
515
|
-
# elsif input =~ /^log_level/ # hidden for now
|
|
516
|
-
# log_level = input.sub(/^log_level\s*/, '').strip
|
|
517
|
-
# if log_level == ""
|
|
518
|
-
# puts "#{Morpheus::Logging.log_level}"
|
|
519
|
-
elsif input == "debug"
|
|
520
|
-
log_history_command(input)
|
|
521
|
-
return Morpheus::Cli::LogLevelCommand.new.handle(["debug"])
|
|
522
498
|
elsif ["hello","hi","hey","hola"].include?(input.strip.downcase)
|
|
523
|
-
|
|
499
|
+
# need a logged_in? method already damnit
|
|
500
|
+
#wallet = @wallet
|
|
501
|
+
wallet = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials
|
|
502
|
+
if wallet
|
|
503
|
+
# my_terminal.echo("#{input} %username!")
|
|
504
|
+
# todo: this morning|afternoon|evening would be pleasant
|
|
505
|
+
print "#{input} #{green}#{wallet['username']}#{reset}, how may I #{cyan}help#{reset} you?\n"
|
|
506
|
+
else
|
|
507
|
+
print "#{input}, how may I #{cyan}help#{reset} you?\n"
|
|
508
|
+
end
|
|
524
509
|
return 0
|
|
525
510
|
elsif input == "shell"
|
|
526
511
|
print "#{cyan}You are already in a shell.#{reset}\n"
|
|
@@ -531,21 +516,31 @@ class Morpheus::Cli::Shell
|
|
|
531
516
|
return Morpheus::Cli::SourceCommand.new.handle(input.split[1..-1])
|
|
532
517
|
end
|
|
533
518
|
cmd_result = nil
|
|
534
|
-
unless input =~ /log-level/
|
|
535
|
-
@return_to_log_level = Morpheus::Logging.log_level
|
|
536
|
-
end
|
|
537
|
-
unless input =~ /coloring/
|
|
538
|
-
@return_to_coloring = Term::ANSIColor::coloring?
|
|
539
|
-
end
|
|
540
519
|
begin
|
|
541
520
|
argv = Shellwords.shellsplit(input)
|
|
542
521
|
cmd_name = argv[0]
|
|
543
522
|
cmd_args = argv[1..-1]
|
|
523
|
+
# crap hack, naming conflicts can occur with aliases
|
|
524
|
+
@return_to_log_level = ["log-level","debug"].include?(cmd_name) ? nil : Morpheus::Logging.log_level
|
|
525
|
+
@return_to_coloring = ["coloring"].include?(cmd_name) ? nil : Term::ANSIColor::coloring?
|
|
526
|
+
@return_to_benchmarking = ["benchmark"].include?(cmd_name) ? nil : Morpheus::Benchmarking.enabled?
|
|
527
|
+
|
|
544
528
|
if Morpheus::Cli::CliRegistry.has_command?(cmd_name) || Morpheus::Cli::CliRegistry.has_alias?(cmd_name)
|
|
545
529
|
#log_history_command(input)
|
|
530
|
+
# start a benchmark, unless the command is benchmark of course
|
|
531
|
+
if my_terminal.benchmarking || cmd_args.include?("-B") || cmd_args.include?("--benchmark")
|
|
532
|
+
if cmd_name != 'benchmark' # jd: this does not work still 2 of them printed.. fix it!
|
|
533
|
+
# benchmark_name = "morpheus " + argv.reject {|it| it == '-B' || it == '--benchmark' }.join(' ')
|
|
534
|
+
benchmark_name = argv.reject {|it| it == '-B' || it == '--benchmark' }.join(' ')
|
|
535
|
+
start_benchmark(benchmark_name)
|
|
536
|
+
end
|
|
537
|
+
end
|
|
546
538
|
cmd_result = Morpheus::Cli::CliRegistry.exec(cmd_name, cmd_args)
|
|
539
|
+
cmd_exit_code, cmd_err = parse_command_result(cmd_result)
|
|
540
|
+
benchmark_record = stop_benchmark(cmd_exit_code, cmd_err) # if benchmarking?
|
|
541
|
+
Morpheus::Logging::DarkPrinter.puts(cyan + dark + benchmark_record.msg) if benchmark_record
|
|
547
542
|
else
|
|
548
|
-
puts_error "#{Morpheus::Terminal.angry_prompt}'#{cmd_name}' is not
|
|
543
|
+
puts_error "#{Morpheus::Terminal.angry_prompt}'#{cmd_name}' is not recognized. Use 'help' to see the list of available commands."
|
|
549
544
|
@history_logger.warn "Unrecognized Command #{cmd_name}" if @history_logger
|
|
550
545
|
cmd_result = -1
|
|
551
546
|
end
|
|
@@ -571,6 +566,11 @@ class Morpheus::Cli::Shell
|
|
|
571
566
|
Term::ANSIColor::coloring = @return_to_coloring
|
|
572
567
|
@return_to_coloring = nil
|
|
573
568
|
end
|
|
569
|
+
if @return_to_benchmarking != nil
|
|
570
|
+
Morpheus::Benchmarking.enabled = @return_to_benchmarking
|
|
571
|
+
my_terminal.benchmarking = Morpheus::Benchmarking.enabled
|
|
572
|
+
@return_to_benchmarking = nil
|
|
573
|
+
end
|
|
574
574
|
end
|
|
575
575
|
|
|
576
576
|
# commands should be a number or nil (treated as 0)
|
|
@@ -664,7 +664,67 @@ class Morpheus::Cli::Shell
|
|
|
664
664
|
@last_command_number += 1
|
|
665
665
|
@history[@last_command_number] = cmd
|
|
666
666
|
if @history_logger
|
|
667
|
-
@history_logger.info "#{@current_username}@#{@appliance_name}
|
|
667
|
+
@history_logger.info "#{@current_username}@#{@appliance_name} -- : (cmd #{@last_command_number}) #{cmd}"
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
def last_command(n=25)
|
|
672
|
+
return list_history_commands(max:1)[0]
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
# list the N most recent commands, sorted oldest -> newest
|
|
676
|
+
# todo: support sort and order options..
|
|
677
|
+
def list_history_commands(options={})
|
|
678
|
+
history_records = []
|
|
679
|
+
max = options[:max] ? options[:max].to_i : 25
|
|
680
|
+
max = 50
|
|
681
|
+
load_history_from_log_file if !@history
|
|
682
|
+
cmd_numbers = @history.keys.last(max.to_i)
|
|
683
|
+
history_records = cmd_numbers.collect { |cmd_number| {command_number: cmd_number, command: @history[cmd_number]} }
|
|
684
|
+
last_cmd = cmd_numbers.last ? @history[cmd_numbers.last] : nil
|
|
685
|
+
# if input != last_cmd # no consecutive
|
|
686
|
+
# log_history_command(input)
|
|
687
|
+
# end
|
|
688
|
+
return history_records
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
def print_history(n)
|
|
692
|
+
n ||= 25
|
|
693
|
+
load_history_from_log_file if !@history
|
|
694
|
+
cmd_numbers = @history.keys.last(n.to_i)
|
|
695
|
+
if cmd_numbers.size == 1
|
|
696
|
+
puts "Last command"
|
|
697
|
+
else
|
|
698
|
+
puts "Last #{cmd_numbers.size} commands"
|
|
668
699
|
end
|
|
700
|
+
print cyan
|
|
701
|
+
cmd_numbers.each do |cmd_number|
|
|
702
|
+
cmd = @history[cmd_number]
|
|
703
|
+
puts "#{cmd_number.to_s.rjust(3, ' ')} #{cmd}"
|
|
704
|
+
end
|
|
705
|
+
print reset
|
|
706
|
+
#last_cmd = cmd_numbers.last ? @history[cmd_numbers.last] : nil
|
|
707
|
+
# if input != last_cmd # no consecutive
|
|
708
|
+
# log_history_command(input)
|
|
709
|
+
# end
|
|
710
|
+
return 0
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
def history_commands_count()
|
|
714
|
+
load_history_from_log_file if !@history
|
|
715
|
+
@history.keys.size
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
def flush_history(n=nil)
|
|
719
|
+
# todo: support only flushing last n commands
|
|
720
|
+
file_path = history_file_path
|
|
721
|
+
if File.exists?(file_path)
|
|
722
|
+
File.truncate(file_path, 0)
|
|
723
|
+
end
|
|
724
|
+
@history = {}
|
|
725
|
+
@last_command_number = 0
|
|
726
|
+
@history_logger = load_history_logger
|
|
727
|
+
print cyan, "Command history flushed!", reset, "\n"
|
|
728
|
+
return 0
|
|
669
729
|
end
|
|
670
730
|
end
|