morpheus-cli 5.5.2.1 → 5.5.3

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 (117) 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/roles.rb +6 -3
  65. data/lib/morpheus/cli/commands/security_groups.rb +1 -1
  66. data/lib/morpheus/cli/commands/shell.rb +40 -62
  67. data/lib/morpheus/cli/commands/snapshots.rb +3 -5
  68. data/lib/morpheus/cli/commands/source_command.rb +8 -16
  69. data/lib/morpheus/cli/commands/storage_providers_command.rb +7 -7
  70. data/lib/morpheus/cli/commands/tasks.rb +2 -2
  71. data/lib/morpheus/cli/commands/vdi_pools_command.rb +6 -6
  72. data/lib/morpheus/cli/commands/view.rb +5 -1
  73. data/lib/morpheus/cli/commands/whitelabel_settings_command.rb +4 -4
  74. data/lib/morpheus/cli/commands/whoami.rb +2 -2
  75. data/lib/morpheus/cli/credentials.rb +30 -8
  76. data/lib/morpheus/cli/dot_file.rb +8 -15
  77. data/lib/morpheus/cli/error_handler.rb +16 -0
  78. data/lib/morpheus/cli/errors.rb +8 -1
  79. data/lib/morpheus/cli/mixins/print_helper.rb +17 -13
  80. data/lib/morpheus/cli/mixins/rest_command.rb +18 -18
  81. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +12 -12
  82. data/lib/morpheus/cli/option_parser.rb +5 -1
  83. data/lib/morpheus/cli/option_types.rb +59 -12
  84. data/lib/morpheus/cli/version.rb +1 -1
  85. data/lib/morpheus/cli.rb +26 -16
  86. data/lib/morpheus/ext/rest_client.rb +3 -2
  87. data/lib/morpheus/formatters.rb +1 -1
  88. data/lib/morpheus/logging.rb +4 -4
  89. data/lib/morpheus/morpkg.rb +4 -4
  90. data/lib/morpheus/rest_client.rb +2 -2
  91. data/lib/morpheus/routes.rb +2 -2
  92. data/lib/morpheus/terminal.rb +65 -16
  93. data/lib/morpheus.rb +1 -1
  94. data/morpheus-cli.gemspec +1 -0
  95. data/test/api/containers_interface_test.rb +68 -0
  96. data/test/api/doc_interface_test.rb +35 -0
  97. data/test/api/instances_interface_test.rb +22 -0
  98. data/test/api/whoami_interface_test.rb +14 -0
  99. data/test/cli/access_token_test.rb +36 -0
  100. data/test/cli/auth_test.rb +82 -0
  101. data/test/cli/cli_test.rb +48 -0
  102. data/test/cli/containers_test.rb +92 -0
  103. data/test/cli/doc_test.rb +35 -0
  104. data/test/cli/help_test.rb +25 -0
  105. data/test/cli/instances_test.rb +36 -0
  106. data/test/cli/man_test.rb +14 -0
  107. data/test/cli/remote_test.rb +89 -0
  108. data/test/cli/roles_test.rb +34 -0
  109. data/test/cli/shell_test.rb +81 -0
  110. data/test/cli/version_test.rb +23 -0
  111. data/test/cli/view_test.rb +55 -0
  112. data/test/cli/whoami_test.rb +17 -0
  113. data/test/morpheus_test.rb +16 -0
  114. data/test/test_case.rb +338 -0
  115. data/test/test_config.rb +137 -0
  116. data/test/test_data_helper.rb +97 -0
  117. 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