morpheus-cli 5.5.2.2 → 5.5.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) 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 +20 -2
  8. data/lib/morpheus/api/appliance_settings_interface.rb +15 -0
  9. data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
  10. data/lib/morpheus/api/archive_files_interface.rb +3 -3
  11. data/lib/morpheus/api/clients_interface.rb +2 -2
  12. data/lib/morpheus/api/clusters_interface.rb +8 -1
  13. data/lib/morpheus/api/containers_interface.rb +29 -16
  14. data/lib/morpheus/api/custom_instance_types_interface.rb +0 -2
  15. data/lib/morpheus/api/cypher_interface.rb +1 -2
  16. data/lib/morpheus/api/doc_interface.rb +8 -6
  17. data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
  18. data/lib/morpheus/api/guidance_settings_interface.rb +17 -0
  19. data/lib/morpheus/api/health_interface.rb +1 -1
  20. data/lib/morpheus/api/image_builder_interface.rb +3 -3
  21. data/lib/morpheus/api/instances_interface.rb +25 -0
  22. data/lib/morpheus/api/logs_interface.rb +2 -4
  23. data/lib/morpheus/api/monitoring_interface.rb +6 -6
  24. data/lib/morpheus/api/monitoring_settings_interface.rb +25 -0
  25. data/lib/morpheus/api/network_server_groups_interface.rb +7 -0
  26. data/lib/morpheus/api/packages_interface.rb +1 -1
  27. data/lib/morpheus/api/reports_interface.rb +1 -1
  28. data/lib/morpheus/api/servers_interface.rb +9 -1
  29. data/lib/morpheus/api/storage_providers_interface.rb +2 -2
  30. data/lib/morpheus/api/virtual_images_interface.rb +1 -1
  31. data/lib/morpheus/api.rb +2 -0
  32. data/lib/morpheus/benchmarking.rb +1 -1
  33. data/lib/morpheus/cli/cli_command.rb +79 -37
  34. data/lib/morpheus/cli/cli_registry.rb +19 -10
  35. data/lib/morpheus/cli/commands/access_token_command.rb +1 -1
  36. data/lib/morpheus/cli/commands/appliance_settings_command.rb +57 -2
  37. data/lib/morpheus/cli/commands/apps.rb +1 -1
  38. data/lib/morpheus/cli/commands/archives_command.rb +25 -33
  39. data/lib/morpheus/cli/commands/backup_settings_command.rb +1 -1
  40. data/lib/morpheus/cli/commands/blueprints_command.rb +10 -21
  41. data/lib/morpheus/cli/commands/boot_scripts_command.rb +2 -2
  42. data/lib/morpheus/cli/commands/cat_command.rb +1 -1
  43. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +18 -13
  44. data/lib/morpheus/cli/commands/clouds.rb +3 -3
  45. data/lib/morpheus/cli/commands/clusters.rb +154 -3
  46. data/lib/morpheus/cli/commands/containers_command.rb +398 -253
  47. data/lib/morpheus/cli/commands/cypher_command.rb +3 -0
  48. data/lib/morpheus/cli/commands/deployments.rb +1 -1
  49. data/lib/morpheus/cli/commands/deploys.rb +9 -9
  50. data/lib/morpheus/cli/commands/doc.rb +15 -16
  51. data/lib/morpheus/cli/commands/execution_request_command.rb +2 -2
  52. data/lib/morpheus/cli/commands/file_copy_request_command.rb +5 -5
  53. data/lib/morpheus/cli/commands/groups.rb +2 -2
  54. data/lib/morpheus/cli/commands/guidance_command.rb +2 -2
  55. data/lib/morpheus/cli/commands/guidance_settings.rb +148 -0
  56. data/lib/morpheus/cli/commands/health_command.rb +4 -4
  57. data/lib/morpheus/cli/commands/hosts.rb +43 -5
  58. data/lib/morpheus/cli/commands/image_builder_command.rb +1 -1
  59. data/lib/morpheus/cli/commands/instances.rb +419 -148
  60. data/lib/morpheus/cli/commands/integrations_command.rb +22 -20
  61. data/lib/morpheus/cli/commands/key_pairs.rb +2 -2
  62. data/lib/morpheus/cli/commands/library_container_scripts_command.rb +2 -2
  63. data/lib/morpheus/cli/commands/library_container_templates_command.rb +2 -2
  64. data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -3
  65. data/lib/morpheus/cli/commands/library_spec_templates_command.rb +2 -2
  66. data/lib/morpheus/cli/commands/log_settings_command.rb +1 -1
  67. data/lib/morpheus/cli/commands/login.rb +1 -1
  68. data/lib/morpheus/cli/commands/man_command.rb +32 -18
  69. data/lib/morpheus/cli/commands/monitoring_settings.rb +228 -0
  70. data/lib/morpheus/cli/commands/network_server_groups_command.rb +222 -0
  71. data/lib/morpheus/cli/commands/packages_command.rb +11 -11
  72. data/lib/morpheus/cli/commands/plugins.rb +1 -1
  73. data/lib/morpheus/cli/commands/policies_command.rb +4 -4
  74. data/lib/morpheus/cli/commands/preseed_scripts_command.rb +2 -2
  75. data/lib/morpheus/cli/commands/provisioning_settings_command.rb +1 -1
  76. data/lib/morpheus/cli/commands/remote.rb +1 -1
  77. data/lib/morpheus/cli/commands/reports_command.rb +13 -3
  78. data/lib/morpheus/cli/commands/security_groups.rb +1 -1
  79. data/lib/morpheus/cli/commands/shell.rb +40 -62
  80. data/lib/morpheus/cli/commands/snapshots.rb +3 -5
  81. data/lib/morpheus/cli/commands/source_command.rb +8 -16
  82. data/lib/morpheus/cli/commands/storage_providers_command.rb +7 -7
  83. data/lib/morpheus/cli/commands/tasks.rb +2 -2
  84. data/lib/morpheus/cli/commands/vdi_pools_command.rb +6 -6
  85. data/lib/morpheus/cli/commands/view.rb +5 -1
  86. data/lib/morpheus/cli/commands/whitelabel_settings_command.rb +5 -5
  87. data/lib/morpheus/cli/commands/whoami.rb +2 -2
  88. data/lib/morpheus/cli/credentials.rb +30 -8
  89. data/lib/morpheus/cli/dot_file.rb +8 -15
  90. data/lib/morpheus/cli/error_handler.rb +16 -0
  91. data/lib/morpheus/cli/errors.rb +8 -1
  92. data/lib/morpheus/cli/mixins/print_helper.rb +17 -13
  93. data/lib/morpheus/cli/mixins/provisioning_helper.rb +14 -12
  94. data/lib/morpheus/cli/mixins/rest_command.rb +23 -19
  95. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +47 -24
  96. data/lib/morpheus/cli/option_parser.rb +5 -1
  97. data/lib/morpheus/cli/option_types.rb +59 -12
  98. data/lib/morpheus/cli/version.rb +1 -1
  99. data/lib/morpheus/cli.rb +26 -16
  100. data/lib/morpheus/ext/rest_client.rb +3 -2
  101. data/lib/morpheus/ext/string.rb +6 -4
  102. data/lib/morpheus/formatters.rb +1 -1
  103. data/lib/morpheus/logging.rb +4 -4
  104. data/lib/morpheus/morpkg.rb +4 -4
  105. data/lib/morpheus/rest_client.rb +2 -2
  106. data/lib/morpheus/routes.rb +41 -9
  107. data/lib/morpheus/terminal.rb +65 -16
  108. data/lib/morpheus.rb +1 -1
  109. data/morpheus-cli.gemspec +1 -0
  110. data/test/api/containers_interface_test.rb +68 -0
  111. data/test/api/doc_interface_test.rb +35 -0
  112. data/test/api/instances_interface_test.rb +22 -0
  113. data/test/api/whoami_interface_test.rb +14 -0
  114. data/test/cli/access_token_test.rb +36 -0
  115. data/test/cli/auth_test.rb +82 -0
  116. data/test/cli/cli_test.rb +48 -0
  117. data/test/cli/containers_test.rb +92 -0
  118. data/test/cli/doc_test.rb +35 -0
  119. data/test/cli/help_test.rb +25 -0
  120. data/test/cli/instances_test.rb +36 -0
  121. data/test/cli/man_test.rb +14 -0
  122. data/test/cli/remote_test.rb +89 -0
  123. data/test/cli/roles_test.rb +34 -0
  124. data/test/cli/shell_test.rb +81 -0
  125. data/test/cli/version_test.rb +23 -0
  126. data/test/cli/view_test.rb +55 -0
  127. data/test/cli/whoami_test.rb +17 -0
  128. data/test/morpheus_test.rb +16 -0
  129. data/test/test_case.rb +338 -0
  130. data/test/test_config.rb +137 -0
  131. data/test/test_data_helper.rb +97 -0
  132. metadata +67 -3
@@ -0,0 +1,7 @@
1
+ require 'morpheus/api/secondary_rest_interface'
2
+
3
+ class Morpheus::NetworkServerGroupsInterface < Morpheus::SecondaryRestInterface
4
+ def base_path(network_server_id)
5
+ "/api/networks/servers/#{network_server_id}/groups"
6
+ end
7
+ end
@@ -79,7 +79,7 @@ class Morpheus::PackagesInterface < Morpheus::APIClient
79
79
  headers = { params: params, authorization: "Bearer #{@access_token}" }
80
80
  opts = {method: :post, url: url, headers: headers}
81
81
  # execute(opts, {parse_json: false})
82
- if Dir.exists?(outfile)
82
+ if Dir.exist?(outfile)
83
83
  raise "outfile is invalid. It is the name of an existing directory: #{outfile}"
84
84
  end
85
85
  # if @verify_ssl == false
@@ -44,7 +44,7 @@ class Morpheus::ReportsInterface < Morpheus::APIClient
44
44
  headers = { params: params, authorization: "Bearer #{@access_token}" }
45
45
  opts = {method: :get, url: url, headers: headers, timeout: 172800}
46
46
  # execute(opts, {parse_json: false})
47
- if Dir.exists?(outfile)
47
+ if Dir.exist?(outfile)
48
48
  raise "outfile is invalid. It is the name of an existing directory: #{outfile}"
49
49
  end
50
50
  # if @verify_ssl == false
@@ -55,6 +55,14 @@ class Morpheus::ServersInterface < Morpheus::APIClient
55
55
  execute(opts)
56
56
  end
57
57
 
58
+ def restart(serverId,payload = {}, params = {})
59
+ url = "#{@base_url}/api/servers/#{serverId}/restart"
60
+
61
+ headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
62
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
63
+ execute(opts)
64
+ end
65
+
58
66
  def make_managed(serverId,payload = {})
59
67
  url = "#{@base_url}/api/servers/#{serverId}/install-agent"
60
68
  #url = "#{@base_url}/api/servers/#{serverId}/make-managed" # added in 4.1
@@ -176,7 +184,7 @@ class Morpheus::ServersInterface < Morpheus::APIClient
176
184
  execute(opts)
177
185
  end
178
186
 
179
- def update_network_label(network_id, server_id, payload)
187
+ def update_network_label(network_id, server_id, payload)
180
188
  url = "#{@base_url}/api/servers/#{server_id}/networkInterfaces/#{network_id}"
181
189
  headers = {authorization: "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
182
190
  opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
@@ -96,7 +96,7 @@ class Morpheus::StorageProvidersInterface < Morpheus::APIClient
96
96
  headers = { params: params, authorization: "Bearer #{@access_token}" }
97
97
  opts = {method: :get, url: url, headers: headers}
98
98
  # execute(opts, false)
99
- if Dir.exists?(outfile)
99
+ if Dir.exist?(outfile)
100
100
  raise "outfile is invalid. It is the name of an existing directory: #{outfile}"
101
101
  end
102
102
  # if @verify_ssl == false
@@ -125,7 +125,7 @@ class Morpheus::StorageProvidersInterface < Morpheus::APIClient
125
125
  headers = { params: params, authorization: "Bearer #{@access_token}" }
126
126
  opts = {method: :get, url: url, headers: headers}
127
127
  # execute(opts, false)
128
- if Dir.exists?(outfile)
128
+ if Dir.exist?(outfile)
129
129
  raise "outfile is invalid. It is the name of an existing directory: #{outfile}"
130
130
  end
131
131
  # if @verify_ssl == false
@@ -81,7 +81,7 @@ class Morpheus::VirtualImagesInterface < Morpheus::APIClient
81
81
  # opts[:verify_ssl] = OpenSSL::SSL::VERIFY_NONE
82
82
  end
83
83
 
84
- start_time = Time.now
84
+ # start_time = Time.now
85
85
  query_params = headers.delete(:params) || {}
86
86
  file_size = image_file.size
87
87
  if File.blockdev?(image_file)
data/lib/morpheus/api.rb CHANGED
@@ -7,4 +7,6 @@ require 'morpheus/formatters'
7
7
 
8
8
  # load interfaces
9
9
  require 'morpheus/api/api_client.rb'
10
+ require 'morpheus/api/rest_interface.rb'
11
+ require 'morpheus/api/read_interface.rb'
10
12
  Dir[File.dirname(__FILE__) + "/api/**/*.rb"].each {|file| require file }
@@ -145,7 +145,7 @@ module Morpheus::Benchmarking
145
145
 
146
146
  # finish the current benchmark and optionally print the time taken.
147
147
  def stop_benchmark(exit_code=0, err=nil)
148
- if @benchmark_record
148
+ if defined?(@benchmark_record) && @benchmark_record
149
149
  @benchmark_record.stop(exit_code, err)
150
150
  @last_benchmark_record = @benchmark_record
151
151
  @benchmark_record = nil
@@ -133,10 +133,12 @@ module Morpheus
133
133
  end
134
134
 
135
135
  # this returns all the options passed in by -O, parsed all nicely into objects.
136
- def parse_passed_options(options)
137
- passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
136
+ def parse_passed_options(options, parse_opts={})
137
+ excludes = [parse_opts[:exclude], parse_opts[:excludes]].flatten.compact
138
+ passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) || excludes.include?(k) } : {}
138
139
  return passed_options
139
140
  end
141
+
140
142
  # Appends Array of OptionType definitions to an OptionParser instance
141
143
  # This adds an option like --fieldContext.fieldName="VALUE"
142
144
  # @param opts [OptionParser]
@@ -378,35 +380,53 @@ module Morpheus
378
380
  end
379
381
  options[:options] = custom_options
380
382
  end
381
- opts.on('-P','--prompt', "Always prompts. Use passed options as the default value.") do |val|
383
+ # --always-prompt can be used with for update commands where it normally defaults to --no-prompt
384
+ opts.on('--prompt', "Always prompt for input on every option, even those not prompted for by default.") do
382
385
  options[:always_prompt] = true
383
- options[:options] ||= {}
384
386
  options[:options][:always_prompt] = true
385
387
  end
386
- opts.on('-N','--no-prompt', "Skip prompts. Use default values for all optional fields.") do |val|
388
+ opts.on('-N','--no-prompt', "No prompt, skips all input prompting.") do |val|
387
389
  options[:no_prompt] = true
388
- options[:options] ||= {}
389
- options[:options][:no_prompt] = true
390
- end
391
-
392
- when :prompt
393
- opts.on('-P','--prompt', "Always prompts. Use passed options as the default value.") do |val|
394
- options[:always_prompt] = true
395
- options[:options] ||= {}
396
- options[:options][:always_prompt] = true
397
- end
398
- opts.on('-N','--no-prompt', "Skip prompts. Use default values for all optional fields.") do |val|
399
- options[:no_prompt] = true
400
- options[:options] ||= {}
401
390
  options[:options][:no_prompt] = true
402
391
  end
392
+ # opts.on('--skip-prompt x,y,z', String, "Skip prompt, do not prompt for input of the specified options.") do |val|
393
+ # options[:skip_prompt] ||= []
394
+ # options[:skip_prompt] += parse_array(val)
395
+ # options[:options][:skip_prompt] = options[:skip_prompt]
396
+ # end
397
+ # opts.on('--only-prompt x,y,z', String, "Only prompt for input on the specified options.") do |val|
398
+ # options[:only_prompt] ||= []
399
+ # options[:only_prompt] += parse_array(val)
400
+ # options[:options][:only_prompt] = options[:only_prompt]
401
+ # end
402
+ opts.on('--no-options', String, "No options, skips all option parsing so no options are required and no default values are used.") do
403
+ options[:no_options] = true
404
+ options[:options][:no_options] = options[:no_options]
405
+ end
406
+ opts.on('--skip-options x,y,z', String, "Skip parsing of the specified options so that they are not required and their default value is not used.") do |val|
407
+ options[:skip_options] ||= []
408
+ options[:skip_options] += parse_array(val)
409
+ options[:options][:skip_options] = options[:skip_options]
410
+ end
411
+ # opts.on('--only-options x,y,z', String, "Only parse the specified options and skip all others.") do |val|
412
+ # options[:only_options] ||= []
413
+ # options[:only_options] += parse_array(val)
414
+ # options[:options][:only_options] = options[:only_options]
415
+ # end
416
+
417
+ # hide these while incubating
418
+ opts.add_hidden_option('--skip-prompt')
419
+ opts.add_hidden_option('--only-prompt')
420
+ opts.add_hidden_option('--no-options')
421
+ opts.add_hidden_option('--skip-options')
422
+ opts.add_hidden_option('--only-options')
403
423
 
404
424
  when :payload
405
425
  opts.on('--payload FILE', String, "Payload from a local JSON or YAML file, skip all prompting") do |val|
406
426
  options[:payload_file] = val.to_s
407
427
  begin
408
428
  payload_file = File.expand_path(options[:payload_file])
409
- if !File.exists?(payload_file) || !File.file?(payload_file)
429
+ if !File.exist?(payload_file) || !File.file?(payload_file)
410
430
  raise ::OptionParser::InvalidOption.new("File not found: #{payload_file}")
411
431
  #return false
412
432
  end
@@ -419,10 +439,10 @@ module Morpheus
419
439
  raise ::OptionParser::InvalidOption.new("Failed to parse payload file: #{payload_file} Error: #{ex.message}")
420
440
  end
421
441
  end
422
- opts.on('--payload-dir DIRECTORY', String, "Payload from a local directory containing 1-N JSON or YAML files, skip all prompting") do |val|
442
+ opts.on('--payload-dir DIRECTORY', String, "Payload from a local directory containing 1-N JSON or YAML files, skip all prompting.") do |val|
423
443
  options[:payload_dir] = val.to_s
424
444
  payload_dir = File.expand_path(options[:payload_dir])
425
- if !Dir.exists?(payload_dir) || !File.directory?(payload_dir)
445
+ if !Dir.exist?(payload_dir) || !File.directory?(payload_dir)
426
446
  raise ::OptionParser::InvalidOption.new("Directory not found: #{payload_dir}")
427
447
  end
428
448
  payload = {}
@@ -592,7 +612,7 @@ module Morpheus
592
612
  end unless excludes.include?(:remote_token)
593
613
  opts.on( '--token-file FILE', String, "Token File, read a file containing the access token." ) do |val|
594
614
  token_file = File.expand_path(val)
595
- if !File.exists?(token_file) || !File.file?(token_file)
615
+ if !File.exist?(token_file) || !File.file?(token_file)
596
616
  raise ::OptionParser::InvalidOption.new("File not found: #{token_file}")
597
617
  end
598
618
  options[:remote_token] = File.read(token_file).to_s.split("\n").first.strip
@@ -609,7 +629,7 @@ module Morpheus
609
629
  end
610
630
  opts.on( '--password-file FILE', String, "Password File, read a file containing the password for authentication." ) do |val|
611
631
  password_file = File.expand_path(val)
612
- if !File.exists?(password_file) || !File.file?(password_file)
632
+ if !File.exist?(password_file) || !File.file?(password_file)
613
633
  raise ::OptionParser::InvalidOption.new("File not found: #{password_file}")
614
634
  end
615
635
  file_content = File.read(password_file) #.strip
@@ -914,12 +934,12 @@ module Morpheus
914
934
 
915
935
  opts.on('--hidden-help', "Print help that includes all the hidden options, like this one." ) do
916
936
  puts opts.full_help_message({show_hidden_options:true})
917
- exit # return 0 maybe?
937
+ exit 0 # return 0 maybe?
918
938
  end
919
939
  opts.add_hidden_option('--hidden-help') if opts.is_a?(Morpheus::Cli::OptionParser)
920
940
  opts.on('-h', '--help', "Print this help" ) do
921
941
  puts opts
922
- exit # return 0 maybe?
942
+ exit 0 # return 0 maybe?
923
943
  end
924
944
 
925
945
  opts
@@ -1012,9 +1032,9 @@ module Morpheus
1012
1032
  out << "\n"
1013
1033
  }
1014
1034
  end
1015
- if command_description
1035
+ if command_description && !command_description.to_s.strip.empty?
1016
1036
  out << "\n"
1017
- out << "#{command_description}\n"
1037
+ out << "#{command_description.strip}\n"
1018
1038
  end
1019
1039
  # out << "\n"
1020
1040
  out
@@ -1248,6 +1268,14 @@ module Morpheus
1248
1268
  true
1249
1269
  end
1250
1270
 
1271
+ def confirm(msg, options)
1272
+ options[:yes] or ::Morpheus::Cli::OptionTypes::confirm(msg, options)
1273
+ end
1274
+
1275
+ def confirm!(msg, options)
1276
+ confirm(msg, options) or raise CommandAborted.new("confirmation declined: #{msg}")
1277
+ end
1278
+
1251
1279
  # The default way to build options for the list command
1252
1280
  # @param [OptionParser] opts
1253
1281
  # @param [Hash] options
@@ -1449,11 +1477,11 @@ module Morpheus
1449
1477
  def validate_outfile(outfile, options)
1450
1478
  full_filename = File.expand_path(outfile)
1451
1479
  outdir = File.dirname(full_filename)
1452
- if Dir.exists?(full_filename)
1480
+ if Dir.exist?(full_filename)
1453
1481
  print_red_alert "[local-file] is invalid. It is the name of an existing directory: #{outfile}"
1454
1482
  return false
1455
1483
  end
1456
- if !Dir.exists?(outdir)
1484
+ if !Dir.exist?(outdir)
1457
1485
  if options[:mkdir]
1458
1486
  print cyan,"Creating local directory #{outdir}",reset,"\n"
1459
1487
  FileUtils.mkdir_p(outdir)
@@ -1462,7 +1490,7 @@ module Morpheus
1462
1490
  return false
1463
1491
  end
1464
1492
  end
1465
- if File.exists?(full_filename) && !options[:overwrite]
1493
+ if File.exist?(full_filename) && !options[:overwrite]
1466
1494
  print_red_alert "[local-file] is invalid. File already exists: #{outfile}\nUse -f to overwrite the existing file."
1467
1495
  return false
1468
1496
  end
@@ -1586,7 +1614,16 @@ module Morpheus
1586
1614
  interface_name = "@#{type.pluralize}_interface"
1587
1615
  interface = instance_variable_get(interface_name)
1588
1616
  if interface.nil?
1589
- raise "#{self.class} has not defined interface #{interface_name}"
1617
+ api_client = instance_variable_get("@api_client")
1618
+ if api_client
1619
+ if api_client.respond_to?(type.pluralize)
1620
+ interface = api_client.send(type.pluralize)
1621
+ else
1622
+ raise "@api_client.#{type.pluralize} is not a recognized interface"
1623
+ end
1624
+ else
1625
+ raise "#{self.class} has not defined interface #{interface_name} or @api_client"
1626
+ end
1590
1627
  end
1591
1628
  begin
1592
1629
  json_response = interface.get(*ids)
@@ -1753,6 +1790,9 @@ module Morpheus
1753
1790
 
1754
1791
  module ClassMethods
1755
1792
 
1793
+ # attr_writer :command_name, :command_description, :hidden_command, :default_refresh_interval,
1794
+ # :subcommands, :hidden_subcommands, :default_subcommand, :subcommand_aliases, :subcommand_descriptions
1795
+
1756
1796
  def prog_name
1757
1797
  "morpheus"
1758
1798
  end
@@ -1779,7 +1819,11 @@ module Morpheus
1779
1819
  # alias :command_name= :set_command_name
1780
1820
 
1781
1821
  def hidden_command
1782
- !!@hidden_command
1822
+ defined?(@hidden_command) && @hidden_command == true
1823
+ end
1824
+
1825
+ def hidden_subcommands
1826
+ @hidden_subcommands ||= []
1783
1827
  end
1784
1828
 
1785
1829
  def set_subcommands_hidden(*cmds)
@@ -1791,7 +1835,7 @@ module Morpheus
1791
1835
  end
1792
1836
 
1793
1837
  def command_description
1794
- @command_description
1838
+ @command_description ||= ""
1795
1839
  end
1796
1840
 
1797
1841
  def set_command_description(val)
@@ -1880,10 +1924,8 @@ module Morpheus
1880
1924
 
1881
1925
  def visible_subcommands
1882
1926
  cmds = subcommands.clone
1883
- if @hidden_subcommands && !@hidden_subcommands.empty?
1884
- @hidden_subcommands.each do |hidden_cmd|
1885
- cmds.delete(hidden_cmd.to_s.gsub('_', '-'))
1886
- end
1927
+ hidden_subcommands.each do |hidden_cmd|
1928
+ cmds.delete(hidden_cmd.to_s.gsub('_', '-'))
1887
1929
  end
1888
1930
  cmds
1889
1931
  end
@@ -78,10 +78,17 @@ module Morpheus
78
78
 
79
79
  def exec_command(command_name, args)
80
80
  #puts "exec_command(#{command_name}, #{args})"
81
+ result = nil
81
82
  if has_alias?(command_name)
82
- exec_alias(command_name, args)
83
+ result = exec_alias(command_name, args)
83
84
  elsif has_command?(command_name)
84
- instance.get(command_name).new.handle(args)
85
+ begin
86
+ result = instance.get(command_name).new.handle(args)
87
+ rescue SystemExit => e
88
+ result = Morpheus::Cli::ErrorHandler.new(Morpheus::Terminal.instance.stderr).handle_error(e) # lol
89
+ rescue => e
90
+ result = Morpheus::Cli::ErrorHandler.new(Morpheus::Terminal.instance.stderr).handle_error(e) # lol
91
+ end
85
92
  else
86
93
  # todo: need to just return error instead of raise
87
94
  msg = "'#{command_name}' is not a morpheus command."
@@ -97,8 +104,10 @@ module Morpheus
97
104
  msg += "\t" + suggestion + "\n"
98
105
  end
99
106
  end
100
- raise CommandNotFoundError.new(msg)
107
+ #raise CommandNotFoundError.new(msg)
108
+ result = Morpheus::Cli::ErrorHandler.new(Morpheus::Terminal.instance.stderr).handle_error(CommandNotFoundError.new(msg)) # lol
101
109
  end
110
+ return result
102
111
  end
103
112
 
104
113
  def exec_alias(alias_name, args)
@@ -248,17 +257,17 @@ module Morpheus
248
257
 
249
258
  # parse any object into a command result [exit_code, error]
250
259
  # 0 means success.
251
- # This treats nil, true, or an object success.
252
- # 0 or
253
- # @return [Array] exit_code, error. Success returns [0, nil].
260
+ # This treats nil, true, or an object as success ie. [0, nil]
261
+ # and false is treated as an error [1, error]
262
+ # @return [Array] [exit_code, error]. Success returns [0, nil].
254
263
  def parse_command_result(cmd_result)
255
- exit_code, err = nil, nil
264
+ exit_code, error = nil, nil
256
265
  if cmd_result.is_a?(Array)
257
266
  exit_code = cmd_result[0] || 0
258
- err = cmd_result[1]
267
+ error = cmd_result[1]
259
268
  elsif cmd_result.is_a?(Hash)
260
269
  exit_code = cmd_result[:exit_code] || 0
261
- err = cmd_result[:error] || cmd_result[:err]
270
+ error = cmd_result[:error] || cmd_result[:err]
262
271
  elsif cmd_result == nil || cmd_result == true
263
272
  exit_code = 0
264
273
  elsif cmd_result == false
@@ -279,7 +288,7 @@ module Morpheus
279
288
  exit_code = 0
280
289
  end
281
290
  end
282
- return exit_code, err
291
+ return exit_code, error
283
292
  end
284
293
 
285
294
  def cached_command_list
@@ -116,7 +116,7 @@ class Morpheus::Cli::AccessTokenCommand
116
116
  end
117
117
  opts.on( '--token-file FILE', String, "Refresh Token File, read a file containing the refresh token." ) do |val|
118
118
  token_file = File.expand_path(val)
119
- if !File.exists?(token_file) || !File.file?(token_file)
119
+ if !File.exist?(token_file) || !File.file?(token_file)
120
120
  raise ::OptionParser::InvalidOption.new("File not found: #{token_file}")
121
121
  end
122
122
  options[:refresh_token] = File.read(token_file).to_s.split("\n").first.strip
@@ -6,7 +6,7 @@ class Morpheus::Cli::ApplianceSettingsCommand
6
6
 
7
7
  set_command_name :'appliance-settings'
8
8
 
9
- register_subcommands :get, :update
9
+ register_subcommands :get, :update, :toggle_maintenance, :'reindex'
10
10
 
11
11
  set_default_subcommand :get
12
12
 
@@ -103,7 +103,7 @@ class Morpheus::Cli::ApplianceSettingsCommand
103
103
  print cyan
104
104
  print enabled_zone_types.collect {|it| it['name']}.join(', ')
105
105
  end
106
- print reset "\n"
106
+ print reset, "\n"
107
107
  return 0
108
108
  rescue RestClient::Exception => e
109
109
  print_rest_exception(e, options)
@@ -307,6 +307,61 @@ class Morpheus::Cli::ApplianceSettingsCommand
307
307
  end
308
308
  end
309
309
 
310
+ def toggle_maintenance(args)
311
+ params = {}
312
+ options = {}
313
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
314
+ opts.banner = opts.banner = subcommand_usage()
315
+ opts.on("--enabled [on|off]", String, "Enabled (on) or Disabled (off)") do |val|
316
+ params['enabled'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
317
+ end
318
+ build_standard_update_options(opts, options, [:auto_confirm], [:payload, :options])
319
+ opts.footer = "Toggle maintenance mode."
320
+ end
321
+ optparse.parse!(args)
322
+ connect(options)
323
+ verify_args!(args:args, optparse:optparse, count:0)
324
+ if params['enabled'].nil?
325
+ confirm!("Are you sure you would like to toggle maintenance mode?", options)
326
+ else
327
+ confirm!("Are you sure you would like to toggle maintenance mode: #{params['enabled'] ? 'on' : 'off'}?", options)
328
+ end
329
+ @appliance_settings_interface.setopts(options)
330
+ if options[:dry_run]
331
+ print_dry_run @appliance_settings_interface.dry.maintenance(params)
332
+ return
333
+ end
334
+ json_response = @appliance_settings_interface.maintenance(params)
335
+ render_response(json_response, options) do
336
+ print_green_success "Toggled maintenance mode: '#{params['enabled'] ? 'on' : 'off'}'"
337
+ end
338
+ return 0, nil
339
+ end
340
+
341
+ def reindex(args)
342
+ params = {}
343
+ options = {}
344
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
345
+ opts.banner = opts.banner = subcommand_usage()
346
+ build_standard_update_options(opts, options, [:auto_confirm], [:payload, :options])
347
+ opts.footer = "Reindex all search data."
348
+ end
349
+ optparse.parse!(args)
350
+ connect(options)
351
+ verify_args!(args:args, optparse:optparse, count:0)
352
+ confirm!("Are you sure you would like reindex all search data?", options)
353
+ @appliance_settings_interface.setopts(options)
354
+ if options[:dry_run]
355
+ print_dry_run @appliance_settings_interface.dry.reindex(params)
356
+ return
357
+ end
358
+ json_response = @appliance_settings_interface.reindex(params)
359
+ render_response(json_response, options) do
360
+ print_green_success "Reindexing all search data..."
361
+ end
362
+ return 0, nil
363
+ end
364
+
310
365
  private
311
366
 
312
367
  def format_days(days)
@@ -2260,7 +2260,7 @@ EOT
2260
2260
  build_option_type_options(opts, options, update_wiki_page_option_types)
2261
2261
  opts.on('--file FILE', "File containing the wiki content. This can be used instead of --content") do |filename|
2262
2262
  full_filename = File.expand_path(filename)
2263
- if File.exists?(full_filename)
2263
+ if File.exist?(full_filename)
2264
2264
  params['content'] = File.read(full_filename)
2265
2265
  else
2266
2266
  print_red_alert "File not found: #{full_filename}"