morpheus-cli 5.5.2.2 → 5.5.3.1
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/Dockerfile +1 -1
- data/README.md +57 -4
- data/Rakefile +9 -0
- data/bin/morpheus +4 -4
- data/lib/morpheus/api/api_client.rb +20 -2
- data/lib/morpheus/api/appliance_settings_interface.rb +15 -0
- data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
- data/lib/morpheus/api/archive_files_interface.rb +3 -3
- data/lib/morpheus/api/clients_interface.rb +2 -2
- data/lib/morpheus/api/clusters_interface.rb +8 -1
- data/lib/morpheus/api/containers_interface.rb +29 -16
- data/lib/morpheus/api/custom_instance_types_interface.rb +0 -2
- data/lib/morpheus/api/cypher_interface.rb +1 -2
- data/lib/morpheus/api/doc_interface.rb +8 -6
- data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
- data/lib/morpheus/api/guidance_settings_interface.rb +17 -0
- data/lib/morpheus/api/health_interface.rb +1 -1
- data/lib/morpheus/api/image_builder_interface.rb +3 -3
- data/lib/morpheus/api/instances_interface.rb +25 -0
- data/lib/morpheus/api/logs_interface.rb +2 -4
- data/lib/morpheus/api/monitoring_interface.rb +6 -6
- data/lib/morpheus/api/monitoring_settings_interface.rb +25 -0
- data/lib/morpheus/api/network_server_groups_interface.rb +7 -0
- data/lib/morpheus/api/packages_interface.rb +1 -1
- data/lib/morpheus/api/reports_interface.rb +1 -1
- data/lib/morpheus/api/servers_interface.rb +9 -1
- data/lib/morpheus/api/storage_providers_interface.rb +2 -2
- data/lib/morpheus/api/virtual_images_interface.rb +1 -1
- data/lib/morpheus/api.rb +2 -0
- data/lib/morpheus/benchmarking.rb +1 -1
- data/lib/morpheus/cli/cli_command.rb +79 -37
- data/lib/morpheus/cli/cli_registry.rb +19 -10
- data/lib/morpheus/cli/commands/access_token_command.rb +1 -1
- data/lib/morpheus/cli/commands/appliance_settings_command.rb +57 -2
- data/lib/morpheus/cli/commands/apps.rb +1 -1
- data/lib/morpheus/cli/commands/archives_command.rb +25 -33
- data/lib/morpheus/cli/commands/backup_settings_command.rb +1 -1
- data/lib/morpheus/cli/commands/blueprints_command.rb +10 -21
- data/lib/morpheus/cli/commands/boot_scripts_command.rb +2 -2
- data/lib/morpheus/cli/commands/cat_command.rb +1 -1
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +18 -13
- data/lib/morpheus/cli/commands/clouds.rb +3 -3
- data/lib/morpheus/cli/commands/clusters.rb +154 -3
- data/lib/morpheus/cli/commands/containers_command.rb +398 -253
- data/lib/morpheus/cli/commands/cypher_command.rb +3 -0
- data/lib/morpheus/cli/commands/deployments.rb +1 -1
- data/lib/morpheus/cli/commands/deploys.rb +9 -9
- data/lib/morpheus/cli/commands/doc.rb +15 -16
- data/lib/morpheus/cli/commands/execution_request_command.rb +2 -2
- data/lib/morpheus/cli/commands/file_copy_request_command.rb +5 -5
- data/lib/morpheus/cli/commands/groups.rb +2 -2
- data/lib/morpheus/cli/commands/guidance_command.rb +2 -2
- data/lib/morpheus/cli/commands/guidance_settings.rb +148 -0
- data/lib/morpheus/cli/commands/health_command.rb +4 -4
- data/lib/morpheus/cli/commands/hosts.rb +43 -5
- data/lib/morpheus/cli/commands/image_builder_command.rb +1 -1
- data/lib/morpheus/cli/commands/instances.rb +419 -148
- data/lib/morpheus/cli/commands/integrations_command.rb +22 -20
- data/lib/morpheus/cli/commands/key_pairs.rb +2 -2
- data/lib/morpheus/cli/commands/library_container_scripts_command.rb +2 -2
- data/lib/morpheus/cli/commands/library_container_templates_command.rb +2 -2
- data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -3
- data/lib/morpheus/cli/commands/library_spec_templates_command.rb +2 -2
- data/lib/morpheus/cli/commands/log_settings_command.rb +1 -1
- data/lib/morpheus/cli/commands/login.rb +1 -1
- data/lib/morpheus/cli/commands/man_command.rb +32 -18
- data/lib/morpheus/cli/commands/monitoring_settings.rb +228 -0
- data/lib/morpheus/cli/commands/network_server_groups_command.rb +222 -0
- data/lib/morpheus/cli/commands/packages_command.rb +11 -11
- data/lib/morpheus/cli/commands/plugins.rb +1 -1
- data/lib/morpheus/cli/commands/policies_command.rb +4 -4
- data/lib/morpheus/cli/commands/preseed_scripts_command.rb +2 -2
- data/lib/morpheus/cli/commands/provisioning_settings_command.rb +1 -1
- data/lib/morpheus/cli/commands/remote.rb +1 -1
- data/lib/morpheus/cli/commands/reports_command.rb +13 -3
- data/lib/morpheus/cli/commands/security_groups.rb +1 -1
- data/lib/morpheus/cli/commands/shell.rb +40 -62
- data/lib/morpheus/cli/commands/snapshots.rb +3 -5
- data/lib/morpheus/cli/commands/source_command.rb +8 -16
- data/lib/morpheus/cli/commands/storage_providers_command.rb +7 -7
- data/lib/morpheus/cli/commands/tasks.rb +2 -2
- data/lib/morpheus/cli/commands/vdi_pools_command.rb +6 -6
- data/lib/morpheus/cli/commands/view.rb +5 -1
- data/lib/morpheus/cli/commands/whitelabel_settings_command.rb +5 -5
- data/lib/morpheus/cli/commands/whoami.rb +2 -2
- data/lib/morpheus/cli/credentials.rb +30 -8
- data/lib/morpheus/cli/dot_file.rb +8 -15
- data/lib/morpheus/cli/error_handler.rb +16 -0
- data/lib/morpheus/cli/errors.rb +8 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +17 -13
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +14 -12
- data/lib/morpheus/cli/mixins/rest_command.rb +23 -19
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +47 -24
- data/lib/morpheus/cli/option_parser.rb +5 -1
- data/lib/morpheus/cli/option_types.rb +59 -12
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli.rb +26 -16
- data/lib/morpheus/ext/rest_client.rb +3 -2
- data/lib/morpheus/ext/string.rb +6 -4
- data/lib/morpheus/formatters.rb +1 -1
- data/lib/morpheus/logging.rb +4 -4
- data/lib/morpheus/morpkg.rb +4 -4
- data/lib/morpheus/rest_client.rb +2 -2
- data/lib/morpheus/routes.rb +41 -9
- data/lib/morpheus/terminal.rb +65 -16
- data/lib/morpheus.rb +1 -1
- data/morpheus-cli.gemspec +1 -0
- data/test/api/containers_interface_test.rb +68 -0
- data/test/api/doc_interface_test.rb +35 -0
- data/test/api/instances_interface_test.rb +22 -0
- data/test/api/whoami_interface_test.rb +14 -0
- data/test/cli/access_token_test.rb +36 -0
- data/test/cli/auth_test.rb +82 -0
- data/test/cli/cli_test.rb +48 -0
- data/test/cli/containers_test.rb +92 -0
- data/test/cli/doc_test.rb +35 -0
- data/test/cli/help_test.rb +25 -0
- data/test/cli/instances_test.rb +36 -0
- data/test/cli/man_test.rb +14 -0
- data/test/cli/remote_test.rb +89 -0
- data/test/cli/roles_test.rb +34 -0
- data/test/cli/shell_test.rb +81 -0
- data/test/cli/version_test.rb +23 -0
- data/test/cli/view_test.rb +55 -0
- data/test/cli/whoami_test.rb +17 -0
- data/test/morpheus_test.rb +16 -0
- data/test/test_case.rb +338 -0
- data/test/test_config.rb +137 -0
- data/test/test_data_helper.rb +97 -0
- metadata +67 -3
|
@@ -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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
@@ -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
|
-
|
|
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
|
-
|
|
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', "
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1884
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
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,
|
|
264
|
+
exit_code, error = nil, nil
|
|
256
265
|
if cmd_result.is_a?(Array)
|
|
257
266
|
exit_code = cmd_result[0] || 0
|
|
258
|
-
|
|
267
|
+
error = cmd_result[1]
|
|
259
268
|
elsif cmd_result.is_a?(Hash)
|
|
260
269
|
exit_code = cmd_result[:exit_code] || 0
|
|
261
|
-
|
|
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,
|
|
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.
|
|
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.
|
|
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}"
|