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.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/account_groups_interface.rb +2 -2
  3. data/lib/morpheus/api/accounts_interface.rb +4 -7
  4. data/lib/morpheus/api/api_client.rb +207 -70
  5. data/lib/morpheus/api/app_templates_interface.rb +7 -28
  6. data/lib/morpheus/api/apps_interface.rb +14 -21
  7. data/lib/morpheus/api/archive_buckets_interface.rb +2 -2
  8. data/lib/morpheus/api/archive_files_interface.rb +6 -6
  9. data/lib/morpheus/api/auth_interface.rb +14 -1
  10. data/lib/morpheus/api/blueprints_interface.rb +9 -16
  11. data/lib/morpheus/api/cloud_datastores_interface.rb +1 -1
  12. data/lib/morpheus/api/cloud_policies_interface.rb +1 -1
  13. data/lib/morpheus/api/clouds_interface.rb +18 -21
  14. data/lib/morpheus/api/cypher_interface.rb +19 -28
  15. data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
  16. data/lib/morpheus/api/group_policies_interface.rb +1 -1
  17. data/lib/morpheus/api/groups_interface.rb +4 -4
  18. data/lib/morpheus/api/image_builder_boot_scripts_interface.rb +1 -1
  19. data/lib/morpheus/api/image_builder_image_builds_interface.rb +2 -2
  20. data/lib/morpheus/api/image_builder_preseed_scripts_interface.rb +1 -1
  21. data/lib/morpheus/api/instances_interface.rb +17 -23
  22. data/lib/morpheus/api/logs_interface.rb +7 -10
  23. data/lib/morpheus/api/network_domains_interface.rb +1 -1
  24. data/lib/morpheus/api/network_groups_interface.rb +1 -1
  25. data/lib/morpheus/api/network_pool_servers_interface.rb +1 -1
  26. data/lib/morpheus/api/network_pools_interface.rb +1 -1
  27. data/lib/morpheus/api/network_proxies_interface.rb +1 -1
  28. data/lib/morpheus/api/network_services_interface.rb +1 -1
  29. data/lib/morpheus/api/networks_interface.rb +1 -1
  30. data/lib/morpheus/api/old_cypher_interface.rb +55 -0
  31. data/lib/morpheus/api/packages_interface.rb +1 -1
  32. data/lib/morpheus/api/policies_interface.rb +1 -1
  33. data/lib/morpheus/api/setup_interface.rb +1 -1
  34. data/lib/morpheus/api/storage_providers_interface.rb +1 -1
  35. data/lib/morpheus/api/whoami_interface.rb +1 -1
  36. data/lib/morpheus/benchmarking.rb +277 -0
  37. data/lib/morpheus/cli.rb +6 -22
  38. data/lib/morpheus/cli/access_token_command.rb +172 -0
  39. data/lib/morpheus/cli/accounts.rb +5 -0
  40. data/lib/morpheus/cli/apps.rb +93 -37
  41. data/lib/morpheus/cli/archives_command.rb +0 -2
  42. data/lib/morpheus/cli/auth_command.rb +112 -0
  43. data/lib/morpheus/cli/blueprints_command.rb +50 -13
  44. data/lib/morpheus/cli/change_password_command.rb +148 -0
  45. data/lib/morpheus/cli/cli_command.rb +173 -49
  46. data/lib/morpheus/cli/clouds.rb +15 -5
  47. data/lib/morpheus/cli/command_error.rb +7 -1
  48. data/lib/morpheus/cli/{alias_command.rb → commands/standard/alias_command.rb} +79 -51
  49. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +399 -0
  50. data/lib/morpheus/cli/commands/standard/coloring_command.rb +60 -0
  51. data/lib/morpheus/cli/{curl_command.rb → commands/standard/curl_command.rb} +0 -7
  52. data/lib/morpheus/cli/commands/standard/debug_command.rb +61 -0
  53. data/lib/morpheus/cli/{echo_command.rb → commands/standard/echo_command.rb} +1 -1
  54. data/lib/morpheus/cli/{edit_profile_command.rb → commands/standard/edit_profile_command.rb} +0 -0
  55. data/lib/morpheus/cli/{edit_rc_command.rb → commands/standard/edit_rc_command.rb} +0 -0
  56. data/lib/morpheus/cli/commands/standard/get_prompt_command.rb +39 -0
  57. data/lib/morpheus/cli/commands/standard/history_command.rb +76 -0
  58. data/lib/morpheus/cli/{log_level_command.rb → commands/standard/log_level_command.rb} +1 -1
  59. data/lib/morpheus/cli/{man_command.rb → commands/standard/man_command.rb} +2 -2
  60. data/lib/morpheus/cli/commands/standard/rm_command.rb +14 -0
  61. data/lib/morpheus/cli/commands/standard/set_prompt_command.rb +54 -0
  62. data/lib/morpheus/cli/{sleep_command.rb → commands/standard/sleep_command.rb} +0 -0
  63. data/lib/morpheus/cli/{source_command.rb → commands/standard/source_command.rb} +0 -0
  64. data/lib/morpheus/cli/{ssl_verification_command.rb → commands/standard/ssl_verification_command.rb} +1 -1
  65. data/lib/morpheus/cli/commands/standard/tee_command.rb +14 -0
  66. data/lib/morpheus/cli/{version_command.rb → commands/standard/version_command.rb} +0 -0
  67. data/lib/morpheus/cli/credentials.rb +276 -87
  68. data/lib/morpheus/cli/cypher_command.rb +333 -214
  69. data/lib/morpheus/cli/error_handler.rb +12 -2
  70. data/lib/morpheus/cli/groups.rb +44 -20
  71. data/lib/morpheus/cli/hosts.rb +39 -16
  72. data/lib/morpheus/cli/instances.rb +114 -62
  73. data/lib/morpheus/cli/login.rb +74 -21
  74. data/lib/morpheus/cli/logout.rb +3 -4
  75. data/lib/morpheus/cli/mixins/accounts_helper.rb +50 -18
  76. data/lib/morpheus/cli/mixins/print_helper.rb +207 -42
  77. data/lib/morpheus/cli/old_cypher_command.rb +414 -0
  78. data/lib/morpheus/cli/option_parser.rb +6 -1
  79. data/lib/morpheus/cli/processes_command.rb +3 -0
  80. data/lib/morpheus/cli/remote.rb +11 -17
  81. data/lib/morpheus/cli/roles.rb +17 -17
  82. data/lib/morpheus/cli/security_groups.rb +47 -17
  83. data/lib/morpheus/cli/shell.rb +139 -79
  84. data/lib/morpheus/cli/tenants_command.rb +353 -0
  85. data/lib/morpheus/cli/users.rb +26 -18
  86. data/lib/morpheus/cli/version.rb +1 -1
  87. data/lib/morpheus/cli/whoami.rb +14 -10
  88. data/lib/morpheus/formatters.rb +4 -4
  89. data/lib/morpheus/logging.rb +16 -8
  90. data/lib/morpheus/terminal.rb +63 -34
  91. metadata +28 -15
  92. data/lib/morpheus/cli/coloring_command.rb +0 -45
  93. data/lib/morpheus/cli/set_prompt_command.rb +0 -51
@@ -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 = "Prints the name of the current remote appliance"
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 status_str.include?("error")
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
 
@@ -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
- "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'])
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
- if options[:json]
42
- print JSON.pretty_generate(json_response)
43
- print "\n"
44
- return
45
- end
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
- print_h1 "Morpheus Security Groups"
52
+
48
53
  if security_groups.empty?
49
- print yellow,"No Security Groups currently configured.",reset,"\n"
54
+ print yellow,"No security groups found.",reset,"\n"
50
55
  else
51
56
  active_id = @active_security_group[@appliance_name.to_sym]
52
- security_groups.each do |security_group|
53
- if @active_security_group[@appliance_name.to_sym] == security_group['id']
54
- print cyan, "=> #{security_group['id']}: #{security_group['name']} (#{security_group['description']})\n"
55
- else
56
- print cyan, " #{security_group['id']}: #{security_group['name']} (#{security_group['description']})\n"
57
- end
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
- if active_id
60
- print cyan, "\n# => - current", reset, "\n"
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
- rescue RestClient::Exception => e
93
+ return 0
94
+ rescue RestClient::Exception => e
65
95
  print_rest_exception(e, options)
66
96
  exit 1
67
97
  end
@@ -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, :'flush-history', :reload!, :help, :exit]
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, no saved credentials and no history.") do
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 |json|
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( '-h', '--help', "Prints this help" ) do
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
- # return exitstatus integer for a given command result
239
- #todo: clean up CliCommand return values, handle a few diff types for now
240
- def parse_result_exitstatus(result)
241
- exit_code, err = 0, nil
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
- if parse_result_exitstatus(previous_command_result) != 0
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
- if parse_result_exitstatus(previous_command_result) == 0
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
- n_commands = input.sub(/^history\s?/, '').sub(/\-n\s?/, '')
395
- n_commands = n_commands.empty? ? 25 : n_commands.to_i
396
- cmd_numbers = @history.keys.last(n_commands)
397
- if cmd_numbers.size == 1
398
- puts "Last command"
399
- else
400
- puts "Last #{cmd_numbers.size} commands"
401
- end
402
- cmd_numbers.each do |cmd_number|
403
- cmd = @history[cmd_number]
404
- puts "#{cmd_number.to_s.rjust(3, ' ')} #{cmd}"
405
- end
406
- last_cmd = cmd_numbers.last ? @history[cmd_numbers.last] : nil
407
- if input != last_cmd # no consecutive
408
- log_history_command(input)
409
- end
410
- return 0
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
- file_path = history_file_path
416
- if File.exists?(file_path)
417
- File.truncate(file_path, 0)
418
- end
419
- @history = {}
420
- @last_command_number = 0
421
- @history_logger = load_history_logger
422
- puts "history cleared!"
423
- return 0
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
- print "#{input.capitalize}, how may I #{cyan}help#{reset} you?\n"
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 a morpheus command. Use 'help' to see the list of available commands."
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} : -- : (cmd #{@last_command_number}) #{cmd}"
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