morpheus-cli 3.6.8 → 3.6.9

Sign up to get free protection for your applications and to get access to all the features.
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