morpheus-cli 5.5.2.2 → 5.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/Dockerfile +1 -1
  4. data/README.md +57 -4
  5. data/Rakefile +9 -0
  6. data/bin/morpheus +4 -4
  7. data/lib/morpheus/api/api_client.rb +8 -2
  8. data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
  9. data/lib/morpheus/api/archive_files_interface.rb +3 -3
  10. data/lib/morpheus/api/clients_interface.rb +2 -2
  11. data/lib/morpheus/api/clusters_interface.rb +8 -1
  12. data/lib/morpheus/api/containers_interface.rb +29 -16
  13. data/lib/morpheus/api/custom_instance_types_interface.rb +0 -2
  14. data/lib/morpheus/api/doc_interface.rb +8 -6
  15. data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
  16. data/lib/morpheus/api/health_interface.rb +1 -1
  17. data/lib/morpheus/api/image_builder_interface.rb +3 -3
  18. data/lib/morpheus/api/instances_interface.rb +25 -0
  19. data/lib/morpheus/api/logs_interface.rb +2 -4
  20. data/lib/morpheus/api/monitoring_interface.rb +6 -6
  21. data/lib/morpheus/api/packages_interface.rb +1 -1
  22. data/lib/morpheus/api/reports_interface.rb +1 -1
  23. data/lib/morpheus/api/servers_interface.rb +9 -1
  24. data/lib/morpheus/api/storage_providers_interface.rb +2 -2
  25. data/lib/morpheus/api/virtual_images_interface.rb +1 -1
  26. data/lib/morpheus/api.rb +2 -0
  27. data/lib/morpheus/benchmarking.rb +1 -1
  28. data/lib/morpheus/cli/cli_command.rb +69 -36
  29. data/lib/morpheus/cli/cli_registry.rb +19 -10
  30. data/lib/morpheus/cli/commands/access_token_command.rb +1 -1
  31. data/lib/morpheus/cli/commands/apps.rb +1 -1
  32. data/lib/morpheus/cli/commands/archives_command.rb +25 -33
  33. data/lib/morpheus/cli/commands/blueprints_command.rb +10 -21
  34. data/lib/morpheus/cli/commands/boot_scripts_command.rb +2 -2
  35. data/lib/morpheus/cli/commands/cat_command.rb +1 -1
  36. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +12 -12
  37. data/lib/morpheus/cli/commands/clouds.rb +3 -3
  38. data/lib/morpheus/cli/commands/clusters.rb +154 -3
  39. data/lib/morpheus/cli/commands/containers_command.rb +398 -253
  40. data/lib/morpheus/cli/commands/deployments.rb +1 -1
  41. data/lib/morpheus/cli/commands/deploys.rb +9 -9
  42. data/lib/morpheus/cli/commands/doc.rb +15 -16
  43. data/lib/morpheus/cli/commands/execution_request_command.rb +2 -2
  44. data/lib/morpheus/cli/commands/file_copy_request_command.rb +5 -5
  45. data/lib/morpheus/cli/commands/groups.rb +2 -2
  46. data/lib/morpheus/cli/commands/health_command.rb +4 -4
  47. data/lib/morpheus/cli/commands/hosts.rb +43 -5
  48. data/lib/morpheus/cli/commands/image_builder_command.rb +1 -1
  49. data/lib/morpheus/cli/commands/instances.rb +419 -148
  50. data/lib/morpheus/cli/commands/integrations_command.rb +22 -20
  51. data/lib/morpheus/cli/commands/key_pairs.rb +2 -2
  52. data/lib/morpheus/cli/commands/library_container_scripts_command.rb +2 -2
  53. data/lib/morpheus/cli/commands/library_container_templates_command.rb +2 -2
  54. data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -3
  55. data/lib/morpheus/cli/commands/library_spec_templates_command.rb +2 -2
  56. data/lib/morpheus/cli/commands/login.rb +1 -1
  57. data/lib/morpheus/cli/commands/man_command.rb +32 -18
  58. data/lib/morpheus/cli/commands/packages_command.rb +11 -11
  59. data/lib/morpheus/cli/commands/plugins.rb +1 -1
  60. data/lib/morpheus/cli/commands/policies_command.rb +4 -4
  61. data/lib/morpheus/cli/commands/preseed_scripts_command.rb +2 -2
  62. data/lib/morpheus/cli/commands/remote.rb +1 -1
  63. data/lib/morpheus/cli/commands/reports_command.rb +3 -3
  64. data/lib/morpheus/cli/commands/security_groups.rb +1 -1
  65. data/lib/morpheus/cli/commands/shell.rb +40 -62
  66. data/lib/morpheus/cli/commands/snapshots.rb +3 -5
  67. data/lib/morpheus/cli/commands/source_command.rb +8 -16
  68. data/lib/morpheus/cli/commands/storage_providers_command.rb +7 -7
  69. data/lib/morpheus/cli/commands/tasks.rb +2 -2
  70. data/lib/morpheus/cli/commands/vdi_pools_command.rb +6 -6
  71. data/lib/morpheus/cli/commands/view.rb +5 -1
  72. data/lib/morpheus/cli/commands/whitelabel_settings_command.rb +4 -4
  73. data/lib/morpheus/cli/commands/whoami.rb +2 -2
  74. data/lib/morpheus/cli/credentials.rb +30 -8
  75. data/lib/morpheus/cli/dot_file.rb +8 -15
  76. data/lib/morpheus/cli/error_handler.rb +16 -0
  77. data/lib/morpheus/cli/errors.rb +8 -1
  78. data/lib/morpheus/cli/mixins/print_helper.rb +17 -13
  79. data/lib/morpheus/cli/mixins/rest_command.rb +18 -18
  80. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +12 -12
  81. data/lib/morpheus/cli/option_parser.rb +5 -1
  82. data/lib/morpheus/cli/option_types.rb +59 -12
  83. data/lib/morpheus/cli/version.rb +1 -1
  84. data/lib/morpheus/cli.rb +26 -16
  85. data/lib/morpheus/ext/rest_client.rb +3 -2
  86. data/lib/morpheus/formatters.rb +1 -1
  87. data/lib/morpheus/logging.rb +4 -4
  88. data/lib/morpheus/morpkg.rb +4 -4
  89. data/lib/morpheus/rest_client.rb +2 -2
  90. data/lib/morpheus/routes.rb +2 -2
  91. data/lib/morpheus/terminal.rb +65 -16
  92. data/lib/morpheus.rb +1 -1
  93. data/morpheus-cli.gemspec +1 -0
  94. data/test/api/containers_interface_test.rb +68 -0
  95. data/test/api/doc_interface_test.rb +35 -0
  96. data/test/api/instances_interface_test.rb +22 -0
  97. data/test/api/whoami_interface_test.rb +14 -0
  98. data/test/cli/access_token_test.rb +36 -0
  99. data/test/cli/auth_test.rb +82 -0
  100. data/test/cli/cli_test.rb +48 -0
  101. data/test/cli/containers_test.rb +92 -0
  102. data/test/cli/doc_test.rb +35 -0
  103. data/test/cli/help_test.rb +25 -0
  104. data/test/cli/instances_test.rb +36 -0
  105. data/test/cli/man_test.rb +14 -0
  106. data/test/cli/remote_test.rb +89 -0
  107. data/test/cli/roles_test.rb +34 -0
  108. data/test/cli/shell_test.rb +81 -0
  109. data/test/cli/version_test.rb +23 -0
  110. data/test/cli/view_test.rb +55 -0
  111. data/test/cli/whoami_test.rb +17 -0
  112. data/test/morpheus_test.rb +16 -0
  113. data/test/test_case.rb +338 -0
  114. data/test/test_config.rb +137 -0
  115. data/test/test_data_helper.rb +97 -0
  116. metadata +61 -3
@@ -110,6 +110,13 @@ class Morpheus::Cli::Shell
110
110
  end
111
111
 
112
112
  def handle(args)
113
+ @clean_shell_mode = false
114
+ @execute_mode = false
115
+ @execute_mode_command = nil
116
+ @norc = false
117
+ @temporary_shell_mode = false
118
+ @temporary_home_directory = nil
119
+ @original_home_directory = nil
113
120
  usage = "Usage: morpheus #{command_name}"
114
121
  optparse = Morpheus::Cli::OptionParser.new do |opts|
115
122
  opts.banner = usage
@@ -159,9 +166,7 @@ class Morpheus::Cli::Shell
159
166
  @parent_shell_directories ||= []
160
167
  @parent_shell_directories << my_terminal.home_directory
161
168
  @previous_home_directory = @parent_shell_directories.last
162
- if @original_home_directory.nil?
163
- @original_home_directory = @previous_home_directory
164
- end
169
+ @original_home_directory ||= @previous_home_directory
165
170
 
166
171
  #@norc = true # perhaps?
167
172
  # instead of using TMPDIR, create tmp shell directory inside $MORPHEUS_CLI_HOME/tmp
@@ -171,18 +176,18 @@ class Morpheus::Cli::Shell
171
176
  if !tmpdir
172
177
  tmpdir = File.join(@original_home_directory, "tmp")
173
178
  end
174
- if !File.exists?(tmpdir)
179
+ if !File.exist?(tmpdir)
175
180
  # Morpheus::Logging::DarkPrinter.puts "creating tmpdir #{tmpdir}" if Morpheus::Logging.debug?
176
181
  FileUtils.mkdir_p(tmpdir)
177
182
  end
178
183
  # this won't not happen since we mkdir above
179
- if !File.exists?(tmpdir)
184
+ if !File.exist?(tmpdir)
180
185
  raise_command_error "Temporary directory not found. Use environment variable MORPHEUS_CLI_TMPDIR"
181
186
  end
182
187
  # change to a temporary home directory
183
188
  @temporary_home_directory = File.join(tmpdir, "tmpshell-#{rand().to_s[2..7]}")
184
189
 
185
- #if !File.exists?(@temporary_home_directory)
190
+ #if !File.exist?(@temporary_home_directory)
186
191
  Morpheus::Logging::DarkPrinter.puts "starting temporary shell at #{@temporary_home_directory}" if Morpheus::Logging.debug?
187
192
  FileUtils.mkdir_p(@temporary_home_directory)
188
193
  # end
@@ -209,21 +214,21 @@ class Morpheus::Cli::Shell
209
214
  # not just in shell
210
215
  # .morpheus_profile has aliases
211
216
  # this has already been loaded, probably should reload it...
212
- if File.exists?(File.join(@previous_home_directory, ".morpheus_profile"))
217
+ if File.exist?(File.join(@previous_home_directory, ".morpheus_profile"))
213
218
  FileUtils.cp(File.join(@previous_home_directory, ".morpheus_profile"), File.join(@temporary_home_directory, ".morpheus_profile"))
214
219
  end
215
220
  if @norc != true
216
- if File.exists?(File.join(@previous_home_directory, ".morpheusrc"))
221
+ if File.exist?(File.join(@previous_home_directory, ".morpheusrc"))
217
222
  FileUtils.cp(File.join(@previous_home_directory, ".morpheusrc"), File.join(@temporary_home_directory, ".morpheusrc"))
218
223
  end
219
224
  end
220
- if File.exists?(File.join(@previous_home_directory, "appliances"))
225
+ if File.exist?(File.join(@previous_home_directory, "appliances"))
221
226
  FileUtils.cp(File.join(@previous_home_directory, "appliances"), File.join(@temporary_home_directory, "appliances"))
222
227
  end
223
- if File.exists?(File.join(@previous_home_directory, "credentials"))
228
+ if File.exist?(File.join(@previous_home_directory, "credentials"))
224
229
  FileUtils.cp(File.join(@previous_home_directory, "credentials"), File.join(@temporary_home_directory, "credentials"))
225
230
  end
226
- if File.exists?(File.join(@previous_home_directory, "groups"))
231
+ if File.exist?(File.join(@previous_home_directory, "groups"))
227
232
  FileUtils.cp(File.join(@previous_home_directory, "groups"), File.join(@temporary_home_directory, "groups"))
228
233
  end
229
234
  # stay logged in
@@ -258,7 +263,7 @@ class Morpheus::Cli::Shell
258
263
 
259
264
  # execute startup script
260
265
  if !@norc
261
- if File.exists?(Morpheus::Cli::DotFile.morpheusrc_filename)
266
+ if File.exist?(Morpheus::Cli::DotFile.morpheusrc_filename)
262
267
  @history_logger.info("load source #{Morpheus::Cli::DotFile.morpheusrc_filename}") if @history_logger
263
268
  Morpheus::Cli::DotFile.new(Morpheus::Cli::DotFile.morpheusrc_filename).execute()
264
269
  end
@@ -277,6 +282,8 @@ class Morpheus::Cli::Shell
277
282
  result = 0
278
283
  @exit_now_please = false
279
284
  while !@exit_now_please do
285
+ #Readline.input = my_terminal.stdin
286
+ #Readline.input = $stdin
280
287
  Readline.completion_append_character = " "
281
288
  Readline.completion_proc = @auto_complete
282
289
  Readline.basic_word_break_characters = ""
@@ -335,7 +342,6 @@ class Morpheus::Cli::Shell
335
342
  if input[0..(prog_name.size)] == "#{prog_name} "
336
343
  input = input[(prog_name.size + 1)..-1] || ""
337
344
  end
338
-
339
345
  if !input.empty?
340
346
 
341
347
  if input == 'exit'
@@ -372,7 +378,7 @@ class Morpheus::Cli::Shell
372
378
  out << "\t#{cmd.to_s}\n"
373
379
  }
374
380
  out << "\n"
375
- out << "For more information, see https://github.com/gomorpheus/morpheus-cli/wiki"
381
+ out << "For more information, see https://clidocs.morpheusdata.com"
376
382
  out << "\n"
377
383
  print out
378
384
  return 0
@@ -386,12 +392,12 @@ class Morpheus::Cli::Shell
386
392
  # clear registry
387
393
  Morpheus::Cli::CliRegistry.instance.flush
388
394
  # reload code
389
- Morpheus::Cli.load!
395
+ Morpheus::Cli.reload!
390
396
  # execute startup scripts
391
- if File.exists?(Morpheus::Cli::DotFile.morpheus_profile_filename)
397
+ if File.exist?(Morpheus::Cli::DotFile.morpheus_profile_filename)
392
398
  Morpheus::Cli::DotFile.new(Morpheus::Cli::DotFile.morpheus_profile_filename).execute()
393
399
  end
394
- if File.exists?(Morpheus::Cli::DotFile.morpheusrc_filename)
400
+ if File.exist?(Morpheus::Cli::DotFile.morpheusrc_filename)
395
401
  Morpheus::Cli::DotFile.new(Morpheus::Cli::DotFile.morpheusrc_filename).execute()
396
402
  end
397
403
  # recalculate shell environment
@@ -486,7 +492,11 @@ class Morpheus::Cli::Shell
486
492
  rescue SystemExit => cmdexit
487
493
  # nothing to do, assume the command that exited printed an error already
488
494
  # print "\n"
489
- exit_code, err = cmdexit.status, "Command exited early."
495
+ if cmdexit.success?
496
+ exit_code, err = cmdexit.status, nil
497
+ else
498
+ exit_code, err = cmdexit.status, "Command exited early."
499
+ end
490
500
  rescue => e
491
501
  # some other type of failure..
492
502
  @history_logger.error "#{e.message}" if @history_logger
@@ -514,6 +524,7 @@ class Morpheus::Cli::Shell
514
524
 
515
525
  end
516
526
 
527
+ # wha this?
517
528
  def get_prompt
518
529
 
519
530
  # print cyan,"morpheus > ",reset
@@ -538,10 +549,10 @@ class Morpheus::Cli::Shell
538
549
 
539
550
  def load_history_logger
540
551
  file_path = history_file_path
541
- if !Dir.exists?(File.dirname(file_path))
552
+ if !Dir.exist?(File.dirname(file_path))
542
553
  FileUtils.mkdir_p(File.dirname(file_path))
543
554
  end
544
- if !File.exists?(file_path)
555
+ if !File.exist?(file_path)
545
556
  FileUtils.touch(file_path)
546
557
  FileUtils.chmod(0600, file_path)
547
558
  end
@@ -561,7 +572,13 @@ class Morpheus::Cli::Shell
561
572
 
562
573
  begin
563
574
  file_path = history_file_path
564
- FileUtils.mkdir_p(File.dirname(file_path))
575
+ # if !Dir.exist?(File.dirname(file_path))
576
+ # FileUtils.mkdir_p(File.dirname(file_path))
577
+ # end
578
+ # if !File.exist?(file_path)
579
+ # FileUtils.touch(file_path)
580
+ # FileUtils.chmod(0600, file_path)
581
+ # end
565
582
 
566
583
  File.open(file_path).each_line do |line|
567
584
  # this is pretty goofy, but this looks for the format: (cmd $command_number) $command_string
@@ -578,7 +595,7 @@ class Morpheus::Cli::Shell
578
595
  # for Ctrl+R history searching
579
596
  Readline::HISTORY << cmd
580
597
  end
581
- end
598
+ end unless !File.exist?(file_path)
582
599
  rescue => e
583
600
  # raise e
584
601
  puts_error "failed to load history from log: #{e}"
@@ -587,45 +604,6 @@ class Morpheus::Cli::Shell
587
604
  return @history
588
605
  end
589
606
 
590
- # remove this..
591
- def _old_load_history_from_log_file(n_commands=1000)
592
- @history ||= {}
593
- @last_command_number ||= 0
594
-
595
- begin
596
- if Gem.win_platform?
597
- return @history
598
- end
599
- file_path = history_file_path
600
- FileUtils.mkdir_p(File.dirname(file_path))
601
- # grab extra lines because not all log entries are commands
602
- n_lines = n_commands + 500
603
- history_lines = `tail -n #{n_lines} #{file_path}`.split(/\n/)
604
- command_lines = history_lines.select do |line|
605
- line.match(/\(cmd (\d+)\) (.+)/)
606
- end
607
- command_lines = command_lines.last(n_commands)
608
- command_lines.each do |line|
609
- matches = line.match(/\(cmd (\d+)\) (.+)/)
610
- if matches && matches.size == 3
611
- cmd_number = matches[1].to_i
612
- cmd = matches[2]
613
-
614
- @last_command_number = cmd_number
615
- @history[@last_command_number] = cmd
616
-
617
- # for Ctrl+R history searching
618
- Readline::HISTORY << cmd
619
- end
620
- end
621
- rescue => e
622
- # raise e
623
- # puts "failed to load history from log"
624
- @history = {}
625
- end
626
- return @history
627
- end
628
-
629
607
  def log_history_command(cmd)
630
608
  load_history_from_log_file if !@history
631
609
  #todo: a fast log_history_command, that doesnt need to load the file..
@@ -745,7 +723,7 @@ class Morpheus::Cli::Shell
745
723
  def flush_history(n=nil)
746
724
  # todo: support only flushing last n commands
747
725
  file_path = history_file_path
748
- if File.exists?(file_path)
726
+ if File.exist?(file_path)
749
727
  File.truncate(file_path, 0)
750
728
  end
751
729
  @history = {}
@@ -24,7 +24,7 @@ class Morpheus::Cli::Snapshots
24
24
  optparse = Morpheus::Cli::OptionParser.new do |opts|
25
25
  opts.banner = subcommand_usage("[id]")
26
26
  opts.footer = "Get Snapshot details." + "\n" +
27
- "[snapshotId] is required. This is the id of the snapshot."
27
+ "[id] is required. This is the id of the snapshot."
28
28
  build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
29
29
  end
30
30
  optparse.parse!(args)
@@ -96,14 +96,12 @@ class Morpheus::Cli::Snapshots
96
96
 
97
97
  def remove(args)
98
98
  options = {}
99
- instance = nil
100
99
  snapshot_id = nil
101
-
102
100
  optparse = Morpheus::Cli::OptionParser.new do |opts|
103
- opts.banner = subcommand_usage("[instance]")
101
+ opts.banner = subcommand_usage("[id]")
104
102
  build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
105
103
  opts.footer = "Remove/Delete a snapshot." + "\n" +
106
- "[snapshotId] is required. This is the id of the snapshot to delete."
104
+ "[id] is required. This is the id of the snapshot to delete."
107
105
  end
108
106
 
109
107
  optparse.parse!(args)
@@ -7,7 +7,6 @@ class Morpheus::Cli::SourceCommand
7
7
  set_command_hidden
8
8
 
9
9
  def handle(args)
10
- append_newline = true
11
10
  options = {}
12
11
  optparse = Morpheus::Cli::OptionParser.new do|opts|
13
12
  opts.banner = "Usage: morpheus #{command_name} [file] [file2]"
@@ -15,24 +14,17 @@ class Morpheus::Cli::SourceCommand
15
14
  opts.footer = "This will execute a file as a script where each line is a morpheus command or expression."
16
15
  end
17
16
  optparse.parse!(args)
18
- if args.count < 1
19
- puts optparse
20
- return false # exit 1
21
- end
22
-
17
+ verify_args!(args:args, optparse:optparse, min:1)
18
+ exit_code, err = 0, nil
23
19
  source_files = args
20
+ bad_files = source_files.select { |source_file| !File.exist?(File.expand_path(source_file)) }
21
+ if !bad_files.empty?
22
+ raise_command_error("source file(s) not found: #{bad_files.join(', ')}")
23
+ end
24
24
  source_files.each do |source_file|
25
- # execute a source script
26
- source_file = File.expand_path(source_file)
27
- if File.exists?(source_file)
28
- cmd_results = Morpheus::Cli::DotFile.new(source_file).execute()
29
- else
30
- print_red_alert "file not found: '#{source_file}'"
31
- # return false
32
- end
25
+ Morpheus::Cli::DotFile.new(File.expand_path(source_file)).execute()
33
26
  end
34
-
35
- return true
27
+ return exit_code, err
36
28
  end
37
29
 
38
30
  end
@@ -794,7 +794,7 @@ class Morpheus::Cli::StorageProvidersCommand
794
794
  puts_error "#{command_name} missing argument: [local-file]\n#{optparse}"
795
795
  return 1
796
796
  end
797
- if !File.exists?(local_file_path)
797
+ if !File.exist?(local_file_path)
798
798
  print_error Morpheus::Terminal.angry_prompt
799
799
  puts_error "#{command_name} bad argument: [local-file]\nFile '#{local_file_path}' was not found.\n#{optparse}"
800
800
  return 1
@@ -918,7 +918,7 @@ class Morpheus::Cli::StorageProvidersCommand
918
918
  else
919
919
 
920
920
  # upload file
921
- if !File.exists?(local_file_path) && !File.file?(local_file_path)
921
+ if !File.exist?(local_file_path) && !File.file?(local_file_path)
922
922
  print_error Morpheus::Terminal.angry_prompt
923
923
  puts_error "#{command_name} bad argument: [local-file]\nFile '#{local_file_path}' was not found.\n#{optparse}"
924
924
  return 1
@@ -1016,15 +1016,15 @@ class Morpheus::Cli::StorageProvidersCommand
1016
1016
 
1017
1017
  file_path = file_path.squeeze('/')
1018
1018
  outfile = File.expand_path(outfile)
1019
- if Dir.exists?(outfile)
1019
+ if Dir.exist?(outfile)
1020
1020
  outfile = File.join(outfile, File.basename(file_path))
1021
1021
  end
1022
- if Dir.exists?(outfile)
1022
+ if Dir.exist?(outfile)
1023
1023
  print_red_alert "[local-file] is invalid. It is the name of an existing directory: #{outfile}"
1024
1024
  return 1
1025
1025
  end
1026
1026
  destination_dir = File.dirname(outfile)
1027
- if !Dir.exists?(destination_dir)
1027
+ if !Dir.exist?(destination_dir)
1028
1028
  if do_mkdir
1029
1029
  print cyan,"Creating local directory #{destination_dir}",reset,"\n"
1030
1030
  FileUtils.mkdir_p(destination_dir)
@@ -1033,7 +1033,7 @@ class Morpheus::Cli::StorageProvidersCommand
1033
1033
  return 1
1034
1034
  end
1035
1035
  end
1036
- if File.exists?(outfile)
1036
+ if File.exist?(outfile)
1037
1037
  if do_overwrite
1038
1038
  # uhh need to be careful wih the passed filepath here..
1039
1039
  # don't delete, just overwrite.
@@ -1069,7 +1069,7 @@ class Morpheus::Cli::StorageProvidersCommand
1069
1069
  print red + "ERROR" + reset + " HTTP #{http_response.code}" + "\n"
1070
1070
  end
1071
1071
  # F it, just remove a bad result
1072
- if File.exists?(outfile) && File.file?(outfile)
1072
+ if File.exist?(outfile) && File.file?(outfile)
1073
1073
  Morpheus::Logging::DarkPrinter.puts "Deleting bad file download: #{outfile}" if Morpheus::Logging.debug?
1074
1074
  File.delete(outfile)
1075
1075
  end
@@ -290,7 +290,7 @@ class Morpheus::Cli::Tasks
290
290
  opts.on('--file FILE', "File containing the task script. This can be used instead of --content" ) do |filename|
291
291
  file_params['sourceType'] = 'local' if file_params['sourceType'].nil?
292
292
  full_filename = File.expand_path(filename)
293
- if File.exists?(full_filename)
293
+ if File.exist?(full_filename)
294
294
  file_params['content'] = File.read(full_filename)
295
295
  else
296
296
  print_red_alert "File not found: #{full_filename}"
@@ -673,7 +673,7 @@ class Morpheus::Cli::Tasks
673
673
  opts.on('--file FILE', "File containing the task script. This can be used instead of --content" ) do |filename|
674
674
  file_params['sourceType'] = 'local' if file_params['sourceType'].nil?
675
675
  full_filename = File.expand_path(filename)
676
- if File.exists?(full_filename)
676
+ if File.exist?(full_filename)
677
677
  file_params['content'] = File.read(full_filename)
678
678
  else
679
679
  print_red_alert "File not found: #{full_filename}"
@@ -184,7 +184,7 @@ EOT
184
184
  options[:config_file] = val.to_s
185
185
  file_content = nil
186
186
  full_filename = File.expand_path(options[:config_file])
187
- if File.exists?(full_filename)
187
+ if File.exist?(full_filename)
188
188
  file_content = File.read(full_filename)
189
189
  else
190
190
  print_red_alert "File not found: #{full_filename}"
@@ -194,7 +194,7 @@ EOT
194
194
  config_map = parse_result[:data]
195
195
  if config_map.nil?
196
196
  # todo: bubble up JSON.parse error message
197
- raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
197
+ raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:error]}"
198
198
  #raise_command_error "Failed to parse config as valid YAML or JSON."
199
199
  else
200
200
  params['config'] = config_map
@@ -244,7 +244,7 @@ EOT
244
244
  config_map = parse_result[:data]
245
245
  if config_map.nil?
246
246
  # todo: bubble up JSON.parse error message
247
- raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
247
+ raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:error]}"
248
248
  #raise_command_error "Failed to parse config as valid YAML or JSON."
249
249
  else
250
250
  params['config'] = config_map
@@ -290,7 +290,7 @@ EOT
290
290
  options[:config_file] = val.to_s
291
291
  file_content = nil
292
292
  full_filename = File.expand_path(options[:config_file])
293
- if File.exists?(full_filename)
293
+ if File.exist?(full_filename)
294
294
  file_content = File.read(full_filename)
295
295
  else
296
296
  print_red_alert "File not found: #{full_filename}"
@@ -300,7 +300,7 @@ EOT
300
300
  config_map = parse_result[:data]
301
301
  if config_map.nil?
302
302
  # todo: bubble up JSON.parse error message
303
- raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
303
+ raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:error]}"
304
304
  #raise_command_error "Failed to parse config as valid YAML or JSON."
305
305
  else
306
306
  params['config'] = config_map
@@ -345,7 +345,7 @@ EOT
345
345
  config_map = parse_result[:data]
346
346
  if config_map.nil?
347
347
  # todo: bubble up JSON.parse error message
348
- raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
348
+ raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:error]}"
349
349
  #raise_command_error "Failed to parse config as valid YAML or JSON."
350
350
  else
351
351
  params['config'] = config_map
@@ -17,9 +17,13 @@ class Morpheus::Cli::View
17
17
  optparse = Morpheus::Cli::OptionParser.new do |opts|
18
18
  opts.banner = subcommand_usage("[path] [id]")
19
19
  # debate: should login using /login/ouath-redirect
20
- opts.on('-L', '--login', "Login with the CLI access token before loading the path." ) do
20
+ opts.on('-l', '--login', "Login with the CLI access token before loading the path." ) do
21
21
  options[:login] = true
22
22
  end
23
+ opts.on('-L', '--old-login', "Alias for -l, --login" ) do
24
+ options[:login] = true
25
+ end
26
+ opts.add_hidden_option('-L, --old-login')
23
27
  opts.on('--absolute', "Absolute path, do not search for a matching route to use") do
24
28
  options[:absolute_path] = true
25
29
  end
@@ -596,11 +596,11 @@ class Morpheus::Cli::WhitelabelSettingsCommand
596
596
  outfile = File.expand_path(args[1])
597
597
  outdir = File.dirname(outfile)
598
598
 
599
- if Dir.exists?(outfile)
599
+ if Dir.exist?(outfile)
600
600
  print_red_alert "[local-file] is invalid. It is the name of an existing directory: #{outfile}"
601
601
  return 1
602
602
  end
603
- if !Dir.exists?(outdir)
603
+ if !Dir.exist?(outdir)
604
604
  if options[:mkdir]
605
605
  print cyan,"Creating local directory #{outdir}",reset,"\n"
606
606
  FileUtils.mkdir_p(outdir)
@@ -609,7 +609,7 @@ class Morpheus::Cli::WhitelabelSettingsCommand
609
609
  return 1
610
610
  end
611
611
  end
612
- if File.exists?(outfile) && !options[:overwrite]
612
+ if File.exist?(outfile) && !options[:overwrite]
613
613
  print_red_alert "[local-file] is invalid. File already exists: #{outfile}\nUse -f to overwrite the existing file."
614
614
  return 1
615
615
  end
@@ -636,7 +636,7 @@ class Morpheus::Cli::WhitelabelSettingsCommand
636
636
  if !options[:quiet]
637
637
  print red + "ERROR" + reset + " HTTP #{http_response.code}" + "\n"
638
638
  end
639
- if File.exists?(outfile) && File.file?(outfile)
639
+ if File.exist?(outfile) && File.file?(outfile)
640
640
  Morpheus::Logging::DarkPrinter.puts "Deleting bad file download: #{outfile}" if Morpheus::Logging.debug?
641
641
  File.delete(outfile)
642
642
  end
@@ -92,7 +92,7 @@ EOT
92
92
  # no permissions, or even name stored atm, we should start storing that.
93
93
  # then we can start checking permissions nd restricting command visibility.
94
94
  whoami_response = {
95
- "user": {
95
+ "user" => {
96
96
  "username" => @remote_appliance ? @remote_appliance[:username] : nil
97
97
  },
98
98
  # "isMasterAccount" => true,
@@ -263,7 +263,7 @@ EOT
263
263
 
264
264
  def save_whoami_file(appliance_name, user_id, json_response)
265
265
  fn = File.join(whoami_file_path, appliance_name.to_s, user_id.to_s + ".json")
266
- if !Dir.exists?(File.dirname(fn))
266
+ if !Dir.exist?(File.dirname(fn))
267
267
  FileUtils.mkdir_p(File.dirname(fn))
268
268
  end
269
269
  Morpheus::Logging::DarkPrinter.puts "writing file #{fn}" if Morpheus::Logging.debug?
@@ -112,16 +112,38 @@ module Morpheus
112
112
  end
113
113
  end
114
114
  if username.empty?
115
- print "Username: #{required_blue_prompt} "
116
- username = $stdin.gets.chomp!
115
+ # print "Username: #{required_blue_prompt} "
116
+ # username = $stdin.gets.chomp!
117
+ Readline.completion_append_character = ""
118
+ Readline.basic_word_break_characters = ''
119
+ Readline.completion_proc = nil
120
+ username = Readline.readline("Username: #{required_blue_prompt} ", false).to_s.chomp
117
121
  else
118
122
  print "Username: #{required_blue_prompt} #{username}\n"
119
123
  end
120
124
  if password.empty?
121
- print "Password: #{required_blue_prompt} "
122
- # this should be my_terminal.stdin instead of STDIN and $stdin
123
- password = STDIN.noecho(&:gets).chomp!
124
- print "\n"
125
+ # readline is still echoing secret with 'NUL:'' so just use $stdin on windows for now
126
+ if Morpheus::Cli.windows?
127
+ print "Password: #{required_blue_prompt} "
128
+ # this should be my_terminal.stdin instead of STDIN and $stdin
129
+ password = $stdin.noecho(&:gets).chomp!
130
+ print "\n"
131
+ else
132
+
133
+ Readline.completion_append_character = ""
134
+ Readline.basic_word_break_characters = ''
135
+ Readline.completion_proc = nil
136
+ # needs to work like $stdin.noecho
137
+ Readline.pre_input_hook = lambda {
138
+ Readline.output = File.open('/dev/null', 'w')
139
+ #Readline.output = File.open(Morpheus::Cli.windows? ? 'NUL:' : '/dev/null', 'w')
140
+ #$stdout = File.open(Morpheus::Cli.windows? ? 'NUL:' : '/dev/null', 'w')
141
+ }
142
+ password = Readline.readline("Password: #{required_blue_prompt} ", false).to_s.chomp
143
+ Readline.pre_input_hook = nil
144
+ Readline.output = Morpheus::Terminal.instance.stdout #my_terminal.stdout
145
+ print "\n"
146
+ end
125
147
  else
126
148
  print "Password: #{required_blue_prompt} \n"
127
149
  end
@@ -396,7 +418,7 @@ module Morpheus
396
418
  credential_map.delete(appliance_name.to_sym)
397
419
  begin
398
420
  fn = credentials_file_path
399
- if !Dir.exists?(File.dirname(fn))
421
+ if !Dir.exist?(File.dirname(fn))
400
422
  FileUtils.mkdir_p(File.dirname(fn))
401
423
  end
402
424
  #Morpheus::Logging::DarkPrinter.puts "adding credentials for #{appliance_name} to #{fn}" if Morpheus::Logging.debug?
@@ -433,7 +455,7 @@ module Morpheus
433
455
  credential_map.delete(appliance_name.to_sym)
434
456
  begin
435
457
  fn = credentials_file_path
436
- if !Dir.exists?(File.dirname(fn))
458
+ if !Dir.exist?(File.dirname(fn))
437
459
  FileUtils.mkdir_p(File.dirname(fn))
438
460
  end
439
461
  #Morpheus::Logging::DarkPrinter.puts "renaming credentials from #{appliance_name} to #{new_appliance_name}" if Morpheus::Logging.debug?
@@ -32,13 +32,10 @@ class Morpheus::Cli::DotFile
32
32
  end
33
33
 
34
34
  # execute this file as a morpheus shell script
35
- # @param stop_on_failure [true, false] the will halt execution if a command returns false.
36
- # Default is false, keep going...
37
- # @block [Proc] if a block is given, each command in the file will be yielded to it
38
- # The default is executes the command with the CliRegistry.exec(cmd, args)
35
+ # executes each line in the file as a morpheus expression, ignores empty lines and comments '#'
39
36
  # @return [Array] exit codes of all the commands that were run.
40
- def execute(stop_on_failure=false, &block)
41
- if !File.exists?(@filename)
37
+ def execute()
38
+ if !File.exist?(@filename)
42
39
  print "#{Term::ANSIColor.red}source file not found: #{@filename}#{Term::ANSIColor.reset}\n" # if Morpheus::Logging.debug?
43
40
  else
44
41
  Morpheus::Logging::DarkPrinter.puts "executing source file #{@filename}" if Morpheus::Logging.debug?
@@ -70,11 +67,7 @@ class Morpheus::Cli::DotFile
70
67
  puts "#{red} source file: #{@filename}, line: #{line_num}, command: #{line}, error: #{err}#{reset}"
71
68
  cmd_result = false
72
69
  end
73
- if cmd_result == false
74
- if stop_on_failure
75
- return cmd_results
76
- end
77
- end
70
+ cmd_results << cmd_result
78
71
  end
79
72
  return cmd_results
80
73
  end
@@ -89,10 +82,10 @@ class Morpheus::Cli::DotFile
89
82
  print "#{Term::ANSIColor.dark}Skipping source file save because filename has not been set#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
90
83
  return false
91
84
  end
92
- if !Dir.exists?(File.dirname(@filename))
85
+ if !Dir.exist?(File.dirname(@filename))
93
86
  FileUtils.mkdir_p(File.dirname(@filename))
94
87
  end
95
- if !File.exists?(@filename)
88
+ if !File.exist?(@filename)
96
89
  print "#{Term::ANSIColor.dark}Initializing source file #{@filename}#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
97
90
  FileUtils.touch(@filename)
98
91
  else
@@ -158,10 +151,10 @@ class Morpheus::Cli::DotFile
158
151
  print "#{Term::ANSIColor.dark}Skipping source file save because filename has not been set#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
159
152
  return false
160
153
  end
161
- if !Dir.exists?(File.dirname(@filename))
154
+ if !Dir.exist?(File.dirname(@filename))
162
155
  FileUtils.mkdir_p(File.dirname(@filename))
163
156
  end
164
- if !File.exists?(@filename)
157
+ if !File.exist?(@filename)
165
158
  print "#{Term::ANSIColor.dark}Initializing source file #{@filename}#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
166
159
  FileUtils.touch(@filename)
167
160
  else
@@ -25,6 +25,16 @@ class Morpheus::Cli::ErrorHandler
25
25
  #@stderr.puts "#{dark}Handling error #{err.class} - #{err}#{reset}"
26
26
 
27
27
  case (err)
28
+ when SystemExit
29
+ # nothing to do, assume the command that exited printed an error already
30
+ # print "\n"
31
+ cmdexit = err
32
+ if cmdexit.success?
33
+ exit_code, err = 0, nil
34
+ else
35
+ exit_code, err = cmdexit.status, "Command exited with status: #{cmdexit.status}"
36
+ end
37
+ return exit_code, err
28
38
  # when Morpheus::Cli::CommandNotFoundError
29
39
  # puts_angry_error err.message
30
40
  # @stderr.puts "Try help to see a list of available commands"
@@ -32,6 +42,12 @@ class Morpheus::Cli::ErrorHandler
32
42
  # if err.exit_code
33
43
  # exit_code = err.exit_code
34
44
  # end
45
+ when Morpheus::Cli::CommandAborted
46
+ # user declined a confirmation prompt, do not print anything and exit 9
47
+ do_print_stacktrace = false
48
+ exit_code = err.exit_code if err.exit_code
49
+ # err = err.message
50
+ return
35
51
  when ::OptionParser::InvalidOption, ::OptionParser::AmbiguousOption,
36
52
  ::OptionParser::MissingArgument, ::OptionParser::InvalidArgument,
37
53
  ::OptionParser::NeedlessArgument
@@ -14,7 +14,7 @@ module Morpheus::Cli
14
14
 
15
15
  end
16
16
 
17
- # An error indicating the command was not recoginzed
17
+ # An error indicating the command was not recognized, assigned exit code 127
18
18
  class CommandNotFoundError < CommandError
19
19
 
20
20
  def initialize(msg, args=[], optparse=nil, exit_code=nil)
@@ -40,7 +40,14 @@ module Morpheus::Cli
40
40
  def initialize(msg, args=[], optparse=nil, exit_code=nil)
41
41
  super(msg, args, optparse, exit_code || 1)
42
42
  end
43
+ end
44
+
45
+ # An error indicating the user declined to accept a confirmation prompt, assigned exit code 9
46
+ class CommandAborted < CommandError
43
47
 
48
+ def initialize(msg, args=[], optparse=nil, exit_code=nil)
49
+ super(msg, args, optparse, exit_code || 9)
50
+ end
44
51
  end
45
52
 
46
53
  end