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.
- 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
@@ -760,7 +760,7 @@ EOT
|
|
760
760
|
options[:config_file] = val.to_s
|
761
761
|
file_content = nil
|
762
762
|
full_filename = File.expand_path(options[:config_file])
|
763
|
-
if File.
|
763
|
+
if File.exist?(full_filename)
|
764
764
|
file_content = File.read(full_filename)
|
765
765
|
else
|
766
766
|
print_red_alert "File not found: #{full_filename}"
|
@@ -770,7 +770,7 @@ EOT
|
|
770
770
|
config_map = parse_result[:data]
|
771
771
|
if config_map.nil?
|
772
772
|
# todo: bubble up JSON.parse error message
|
773
|
-
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:
|
773
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:error]}"
|
774
774
|
#raise_command_error "Failed to parse config as valid YAML or JSON."
|
775
775
|
else
|
776
776
|
params['config'] = config_map
|
@@ -813,7 +813,7 @@ EOT
|
|
813
813
|
# config_map = parse_result[:data]
|
814
814
|
# if config_map.nil?
|
815
815
|
# # todo: bubble up JSON.parse error message
|
816
|
-
# raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:
|
816
|
+
# raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:error]}"
|
817
817
|
# #raise_command_error "Failed to parse config as valid YAML or JSON."
|
818
818
|
# else
|
819
819
|
# params['config'] = config_map
|
@@ -1065,26 +1065,28 @@ EOT
|
|
1065
1065
|
return 1, "integration inventory not found for #{args[1]}" if integration_inventory.nil?
|
1066
1066
|
# construct payload
|
1067
1067
|
object_key = integration_inventory_object_key
|
1068
|
-
payload =
|
1069
|
-
if
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
val.
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1068
|
+
payload = parse_payload(options, object_key)
|
1069
|
+
if payload.nil?
|
1070
|
+
if options[:tenants]
|
1071
|
+
#params['tenants'] = options[:tenants]
|
1072
|
+
params['tenants'] = options[:tenants].collect do |val|
|
1073
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
1074
|
+
val.to_i
|
1075
|
+
else
|
1076
|
+
# todo: use /api/options/allTenants to avoid permission errors here..
|
1077
|
+
record = find_by_name_or_id(:account, val)
|
1078
|
+
if record.nil?
|
1079
|
+
exit 1 #return 1, "Tenant not found by '#{val}'"
|
1080
|
+
else
|
1081
|
+
record['id']
|
1082
|
+
end
|
1081
1083
|
end
|
1082
1084
|
end
|
1083
1085
|
end
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1086
|
+
payload.deep_merge!({object_key => params})
|
1087
|
+
if payload.empty? || payload[object_key].empty?
|
1088
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
1089
|
+
end
|
1088
1090
|
end
|
1089
1091
|
# make request
|
1090
1092
|
@integrations_interface.setopts(options)
|
@@ -146,7 +146,7 @@ class Morpheus::Cli::KeyPairs
|
|
146
146
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
147
147
|
opts.banner = subcommand_usage("[name] [options]")
|
148
148
|
opts.on('', '--public-key-file FILENAME', "Public Key File" ) do |filename|
|
149
|
-
if File.
|
149
|
+
if File.exist?(File.expand_path(filename))
|
150
150
|
options['publicKey'] = File.read(File.expand_path(filename))
|
151
151
|
options[:options] ||= {}
|
152
152
|
options[:options]['publicKey'] = options['publicKey']
|
@@ -163,7 +163,7 @@ class Morpheus::Cli::KeyPairs
|
|
163
163
|
end
|
164
164
|
|
165
165
|
opts.on('', '--private-key-file FILENAME', "Private Key File" ) do |filename|
|
166
|
-
if File.
|
166
|
+
if File.exist?(File.expand_path(filename))
|
167
167
|
options['privateKey'] = File.read(File.expand_path(filename))
|
168
168
|
options[:options] ||= {}
|
169
169
|
options[:options]['privateKey'] = options['privateKey']
|
@@ -172,7 +172,7 @@ class Morpheus::Cli::LibraryContainerScriptsCommand
|
|
172
172
|
end
|
173
173
|
opts.on('--file FILE', "File containing the script. This can be used instead of --script" ) do |filename|
|
174
174
|
full_filename = File.expand_path(filename)
|
175
|
-
if File.
|
175
|
+
if File.exist?(full_filename)
|
176
176
|
params['script'] = File.read(full_filename)
|
177
177
|
else
|
178
178
|
print_red_alert "File not found: #{full_filename}"
|
@@ -266,7 +266,7 @@ class Morpheus::Cli::LibraryContainerScriptsCommand
|
|
266
266
|
end
|
267
267
|
opts.on('--file FILE', "File containing the script. This can be used instead of --script" ) do |filename|
|
268
268
|
full_filename = File.expand_path(filename)
|
269
|
-
if File.
|
269
|
+
if File.exist?(full_filename)
|
270
270
|
params['script'] = File.read(full_filename)
|
271
271
|
else
|
272
272
|
print_red_alert "File not found: #{full_filename}"
|
@@ -195,7 +195,7 @@ class Morpheus::Cli::LibraryContainerTemplatesCommand
|
|
195
195
|
end
|
196
196
|
opts.on('--file FILE', "File containing the template. This can be used instead of --template" ) do |filename|
|
197
197
|
full_filename = File.expand_path(filename)
|
198
|
-
if File.
|
198
|
+
if File.exist?(full_filename)
|
199
199
|
params['template'] = File.read(full_filename)
|
200
200
|
else
|
201
201
|
print_red_alert "File not found: #{full_filename}"
|
@@ -312,7 +312,7 @@ class Morpheus::Cli::LibraryContainerTemplatesCommand
|
|
312
312
|
end
|
313
313
|
opts.on('--file FILE', "File containing the template. This can be used instead of --template" ) do |filename|
|
314
314
|
full_filename = File.expand_path(filename)
|
315
|
-
if File.
|
315
|
+
if File.exist?(full_filename)
|
316
316
|
params['template'] = File.read(full_filename)
|
317
317
|
else
|
318
318
|
print_red_alert "File not found: #{full_filename}"
|
@@ -306,7 +306,7 @@ class Morpheus::Cli::LibraryInstanceTypesCommand
|
|
306
306
|
params.deep_merge!(v_prompt)
|
307
307
|
if params['logo']
|
308
308
|
filename = File.expand_path(params['logo'])
|
309
|
-
if !File.
|
309
|
+
if !File.exist?(filename)
|
310
310
|
print_red_alert "File not found: #{filename}"
|
311
311
|
exit 1
|
312
312
|
end
|
@@ -523,7 +523,7 @@ class Morpheus::Cli::LibraryInstanceTypesCommand
|
|
523
523
|
logo_file = 'null' # clear it
|
524
524
|
else
|
525
525
|
filename = File.expand_path(filename)
|
526
|
-
if !File.
|
526
|
+
if !File.exist?(filename)
|
527
527
|
print_red_alert "File not found: #{filename}"
|
528
528
|
exit 1
|
529
529
|
end
|
@@ -571,7 +571,7 @@ class Morpheus::Cli::LibraryInstanceTypesCommand
|
|
571
571
|
dark_logo_file = 'null' # clear it
|
572
572
|
else
|
573
573
|
filename = File.expand_path(filename)
|
574
|
-
if !File.
|
574
|
+
if !File.exist?(filename)
|
575
575
|
print_red_alert "File not found: #{filename}"
|
576
576
|
exit 1
|
577
577
|
end
|
@@ -207,7 +207,7 @@ class Morpheus::Cli::LibrarySpecTemplatesCommand
|
|
207
207
|
opts.on('--file FILE', "File containing the template. This can be used instead of --content" ) do |filename|
|
208
208
|
file_params['sourceType'] = 'local' if file_params['sourceType'].nil?
|
209
209
|
full_filename = File.expand_path(filename)
|
210
|
-
if File.
|
210
|
+
if File.exist?(full_filename)
|
211
211
|
file_params['content'] = File.read(full_filename)
|
212
212
|
else
|
213
213
|
print_red_alert "File not found: #{full_filename}"
|
@@ -363,7 +363,7 @@ class Morpheus::Cli::LibrarySpecTemplatesCommand
|
|
363
363
|
opts.on('--file FILE', "File containing the template. This can be used instead of --content" ) do |filename|
|
364
364
|
file_params['sourceType'] = 'local' if file_params['sourceType'].nil?
|
365
365
|
full_filename = File.expand_path(filename)
|
366
|
-
if File.
|
366
|
+
if File.exist?(full_filename)
|
367
367
|
file_params['content'] = File.read(full_filename)
|
368
368
|
else
|
369
369
|
print_red_alert "File not found: #{full_filename}"
|
@@ -78,7 +78,7 @@ class Morpheus::Cli::LogSettingsCommand
|
|
78
78
|
print cyan
|
79
79
|
print as_pretty_table(log_settings['integrations'], [:name, :enabled, :host, :port])
|
80
80
|
end
|
81
|
-
print reset "\n"
|
81
|
+
print reset, "\n"
|
82
82
|
return 0
|
83
83
|
rescue RestClient::Exception => e
|
84
84
|
print_rest_exception(e, options)
|
@@ -33,7 +33,7 @@ class Morpheus::Cli::Login
|
|
33
33
|
end
|
34
34
|
opts.on( '--password-file FILE', String, "Password File, read a file containing the password." ) do |val|
|
35
35
|
password_file = File.expand_path(val)
|
36
|
-
if !File.
|
36
|
+
if !File.exist?(password_file) || !File.file?(password_file) # check readable too
|
37
37
|
raise ::OptionParser::InvalidOption.new("File not found: #{password_file}")
|
38
38
|
end
|
39
39
|
password = File.read(password_file) #.to_s.split("\n").first.strip
|
@@ -8,12 +8,24 @@ class Morpheus::Cli::ManCommand
|
|
8
8
|
# this should be read only anyway...
|
9
9
|
@@default_editor = "less" # ENV['EDITOR']
|
10
10
|
|
11
|
+
def self.man_file_path
|
12
|
+
File.join(Morpheus::Cli.home_directory, "CLI-Manual-#{Morpheus::Cli::VERSION}.md")
|
13
|
+
end
|
14
|
+
|
11
15
|
def handle(args)
|
12
16
|
options = {}
|
13
17
|
regenerate = false
|
14
|
-
editor = @@default_editor
|
15
18
|
open_as_link = false # true please
|
16
19
|
goto_wiki = false
|
20
|
+
editor = @@default_editor
|
21
|
+
#todo: windows
|
22
|
+
if !$stdin.tty?
|
23
|
+
editor = "cat"
|
24
|
+
end
|
25
|
+
# no editor for windows atm
|
26
|
+
if Morpheus::Cli.windows?
|
27
|
+
open_as_link = true
|
28
|
+
end
|
17
29
|
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
18
30
|
opts.banner = "Usage: morpheus man"
|
19
31
|
opts.on('-w','--wiki', "Open the morpheus-cli wiki instead of the local man page") do
|
@@ -81,16 +93,16 @@ EOT
|
|
81
93
|
print_error "#{red}It is the name of an existing directory.#{reset}\n"
|
82
94
|
return 1
|
83
95
|
end
|
84
|
-
if File.
|
96
|
+
if File.exist?(fn) && options[:overwrite] != true
|
85
97
|
print_error "#{red}Output file '#{fn}' already exists.#{reset}\n"
|
86
98
|
print_error "#{red}Use --overwrite to overwrite the existing file.#{reset}\n"
|
87
99
|
return 1
|
88
100
|
end
|
89
101
|
end
|
90
102
|
exit_code, err = 0, nil
|
91
|
-
if regenerate || !File.
|
103
|
+
if regenerate || !File.exist?(fn)
|
92
104
|
#Morpheus::Logging::DarkPrinter.puts "generating manual #{fn} ..." if Morpheus::Logging.debug? && !options[:quiet]
|
93
|
-
exit_code, err =
|
105
|
+
exit_code, err = generate_manual(options)
|
94
106
|
end
|
95
107
|
|
96
108
|
if options[:quiet]
|
@@ -99,7 +111,7 @@ EOT
|
|
99
111
|
|
100
112
|
Morpheus::Logging::DarkPrinter.puts "opening manual file #{fn}" if Morpheus::Logging.debug? && !options[:quiet]
|
101
113
|
|
102
|
-
if open_as_link #
|
114
|
+
if open_as_link # windows only atm
|
103
115
|
link = "file://#{fn}"
|
104
116
|
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
105
117
|
system "start #{link}"
|
@@ -142,13 +154,9 @@ EOT
|
|
142
154
|
return has_it
|
143
155
|
end
|
144
156
|
|
145
|
-
def self.man_file_path
|
146
|
-
File.join(Morpheus::Cli.home_directory, "CLI-Manual-#{Morpheus::Cli::VERSION}.md")
|
147
|
-
end
|
148
|
-
|
149
157
|
# def self.save_manual(fn, content)
|
150
|
-
# # fn = man_file_path
|
151
|
-
# if !Dir.
|
158
|
+
# # fn = Morpheus::Cli::ManCommand.man_file_path
|
159
|
+
# if !Dir.exist?(File.dirname(fn))
|
152
160
|
# FileUtils.mkdir_p(File.dirname(fn))
|
153
161
|
# end
|
154
162
|
# Morpheus::Logging::DarkPrinter.puts "saving manual to #{fn}" if Morpheus::Logging.debug?
|
@@ -156,19 +164,19 @@ EOT
|
|
156
164
|
# FileUtils.chmod(0600, fn)
|
157
165
|
# end
|
158
166
|
|
159
|
-
def
|
167
|
+
def generate_manual(options={})
|
160
168
|
# todo: use pandoc or something else to convert the CLI-Manual.md to a man page
|
161
169
|
# and install it, so the os command `man morpheus` will work too.
|
162
|
-
fn = man_file_path
|
170
|
+
fn = Morpheus::Cli::ManCommand.man_file_path
|
163
171
|
if options[:outfile]
|
164
172
|
fn = File.expand_path(options[:outfile])
|
165
|
-
if File.
|
173
|
+
if File.exist?(fn) && options[:overwrite] != true
|
166
174
|
print_error "#{red}Output file '#{options[:outfile]}' already exists.#{reset}\n"
|
167
175
|
print_error "#{red}Use --overwrite to overwrite the existing file.#{reset}\n"
|
168
176
|
return 1, "output file already exists"
|
169
177
|
end
|
170
178
|
end
|
171
|
-
if !Dir.
|
179
|
+
if !Dir.exist?(File.dirname(fn))
|
172
180
|
FileUtils.mkdir_p(File.dirname(fn))
|
173
181
|
end
|
174
182
|
Morpheus::Logging::DarkPrinter.puts "generating manual #{fn}" if Morpheus::Logging.debug? && !options[:quiet]
|
@@ -202,7 +210,7 @@ EOT
|
|
202
210
|
|
203
211
|
Use the command `#{prog_name} remote add` to connect to your Morpheus appliance.
|
204
212
|
|
205
|
-
To learn more, visit https://
|
213
|
+
To learn more, visit https://clidocs.morpheusdata.com
|
206
214
|
|
207
215
|
To learn more about the Morpheus Appliance, visit https://www.morpheusdata.com
|
208
216
|
|
@@ -254,7 +262,11 @@ EOT
|
|
254
262
|
The available commands and their options are documented below.
|
255
263
|
ENDTEXT
|
256
264
|
|
257
|
-
|
265
|
+
|
266
|
+
#terminal = Morpheus::Terminal.new($stdin, manpage)
|
267
|
+
terminal = my_terminal
|
268
|
+
terminal.with_stdout(manpage) do
|
269
|
+
|
258
270
|
Morpheus::Logging::DarkPrinter.puts "appending command help `#{prog_name} --help`" if Morpheus::Logging.debug? && !options[:quiet]
|
259
271
|
|
260
272
|
manpage.print "\n"
|
@@ -406,12 +418,14 @@ echo
|
|
406
418
|
```
|
407
419
|
|
408
420
|
ENDTEXT
|
421
|
+
|
422
|
+
end # end with_stdout(manpage)
|
409
423
|
|
410
424
|
ensure
|
411
425
|
manpage.close if manpage
|
412
426
|
# $stdout = previous_stdout if previous_stdout
|
413
427
|
# this is needed to re-establish instance with STDOUT, STDIN
|
414
|
-
terminal = Morpheus::Terminal.new()
|
428
|
+
#terminal = Morpheus::Terminal.new()
|
415
429
|
end
|
416
430
|
|
417
431
|
return 0, nil
|
@@ -0,0 +1,228 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
|
3
|
+
class Morpheus::Cli::MonitoringSettings
|
4
|
+
include Morpheus::Cli::CliCommand
|
5
|
+
include Morpheus::Cli::AccountsHelper
|
6
|
+
|
7
|
+
set_command_name :'monitor-settings'
|
8
|
+
set_command_description "View and manage monitoring settings"
|
9
|
+
register_subcommands :get, :update
|
10
|
+
|
11
|
+
def connect(opts)
|
12
|
+
@api_client = establish_remote_appliance_connection(opts)
|
13
|
+
@monitoring_settings_interface = @api_client.monitoring_settings
|
14
|
+
@options_interface = @api_client.options
|
15
|
+
end
|
16
|
+
|
17
|
+
def handle(args)
|
18
|
+
handle_subcommand(args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get(args)
|
22
|
+
params = {}
|
23
|
+
options = {}
|
24
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
25
|
+
opts.banner = subcommand_usage()
|
26
|
+
build_standard_get_options(opts, options)
|
27
|
+
opts.footer = "Get monitoring settings."
|
28
|
+
end
|
29
|
+
optparse.parse!(args)
|
30
|
+
connect(options)
|
31
|
+
verify_args!(args:args, optparse:optparse, count:0)
|
32
|
+
params.merge!(parse_query_options(options))
|
33
|
+
@monitoring_settings_interface.setopts(options)
|
34
|
+
if options[:dry_run]
|
35
|
+
print_dry_run @monitoring_settings_interface.dry.get(options)
|
36
|
+
return
|
37
|
+
end
|
38
|
+
json_response = @monitoring_settings_interface.get(options)
|
39
|
+
render_response(json_response, options, 'monitoringSettings') do
|
40
|
+
monitoring_settings = json_response['monitoringSettings']
|
41
|
+
service_now_settings = monitoring_settings['serviceNow']
|
42
|
+
new_relic_settings = monitoring_settings['newRelic']
|
43
|
+
print_h1 "Monitoring Settings"
|
44
|
+
print cyan
|
45
|
+
description_cols = {
|
46
|
+
"Auto Create Checks" => lambda {|it| format_boolean(it['autoManageChecks']) },
|
47
|
+
"Availability Time Frame" => lambda {|it| it['availabilityTimeFrame'] ? it['availabilityTimeFrame'].to_s + ' days' : '' },
|
48
|
+
"Availability Precision" => lambda {|it| it['availabilityPrecision'] ? it['availabilityPrecision'].to_s : '' },
|
49
|
+
"Default Check Interval" => lambda {|it| it['defaultCheckInterval'] ? it['defaultCheckInterval'].to_s + ' minutes' : '' },
|
50
|
+
}
|
51
|
+
print_description_list(description_cols, monitoring_settings, options)
|
52
|
+
|
53
|
+
print_h2 "ServiceNow Settings", options.merge(:border_style => :thin)
|
54
|
+
description_cols = {
|
55
|
+
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
56
|
+
"Integration" => lambda {|it| it['integration'] ? it['integration']['name'] : '' },
|
57
|
+
"New Incident Action" => lambda {|it| format_service_now_action(it['newIncidentAction']) },
|
58
|
+
"Close Incident Action" => lambda {|it| format_service_now_action(it['closeIncidentAction']) },
|
59
|
+
"Info Mapping" => lambda {|it| format_service_now_mapping(it['infoMapping']) },
|
60
|
+
"Warning Mapping" => lambda {|it| format_service_now_mapping(it['warningMapping']) },
|
61
|
+
"Critical Mapping" => lambda {|it| format_service_now_mapping(it['criticalMapping']) },
|
62
|
+
}
|
63
|
+
print_description_list(description_cols, service_now_settings)
|
64
|
+
|
65
|
+
print_h2 "New Relic Settings", options.merge(:border_style => :thin)
|
66
|
+
description_cols = {
|
67
|
+
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
68
|
+
"License Key" => lambda {|it| it['licenseKey'] },
|
69
|
+
}
|
70
|
+
print_description_list(description_cols, new_relic_settings, options)
|
71
|
+
|
72
|
+
print reset, "\n"
|
73
|
+
end
|
74
|
+
return 0, nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def update(args)
|
78
|
+
params = {}
|
79
|
+
options = {}
|
80
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
81
|
+
opts.banner = opts.banner = subcommand_usage()
|
82
|
+
opts.on('--auto-create-checks [on|off]', String, "Auto Create Checks") do |val|
|
83
|
+
params['autoManageChecks'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
84
|
+
end
|
85
|
+
opts.on("--availability-time-frame DAYS", Integer, "Availability Time Frame. The number of days availability should be calculated for. Changes will not take effect until your checks have passed their check interval.") do |val|
|
86
|
+
params['availabilityTimeFrame'] = val.to_i
|
87
|
+
end
|
88
|
+
opts.on("--availability-precision DIGITS", Integer, "Availability Precision. The number of decimal places availability should be displayed in. Can be anywhere between 0 and 5.") do |val|
|
89
|
+
params['availabilityPrecision'] = val.to_i
|
90
|
+
end
|
91
|
+
opts.on("--default-check-interval MINUTES", Integer, "Default Check Interval. The default interval to use when creating new checks. Value is in minutes.") do |val|
|
92
|
+
params['defaultCheckInterval'] = val.to_i
|
93
|
+
end
|
94
|
+
opts.on('--service-now-enabled [on|off]', String, "ServiceNow: Enabled (on) or disabled (off)") do |val|
|
95
|
+
params['serviceNow'] ||= {}
|
96
|
+
params['serviceNow']['enabled'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
97
|
+
end
|
98
|
+
opts.on('--service-now-integration ID', String, "ServiceNow: Integration ID or Name") do |val|
|
99
|
+
params['serviceNow'] ||= {}
|
100
|
+
params['serviceNow']['integration'] = val # {'id' => val.to_i}
|
101
|
+
end
|
102
|
+
opts.on("--service-now-new-incident-action create|none", String, "ServiceNow: New Incident Action") do |val|
|
103
|
+
# allowed_values = 'create|none'.split('|') #get_service_now_actions().keys
|
104
|
+
# if !allowed_values.include?(val)
|
105
|
+
# raise ::OptionParser::InvalidOption.new("New Incident Action value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
|
106
|
+
# end
|
107
|
+
params['serviceNow'] ||= {}
|
108
|
+
params['serviceNow']['newIncidentAction'] = val
|
109
|
+
end
|
110
|
+
opts.on("--service-now-close-incident-action close|activity|none", String, "ServiceNow: Close Incident Action") do |val|
|
111
|
+
# allowed_values = 'close|activity|none'.split('|') #get_service_now_mappings().keys
|
112
|
+
# if !allowed_values.include?(val)
|
113
|
+
# raise ::OptionParser::InvalidOption.new("Close Incident Action value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
|
114
|
+
# end
|
115
|
+
params['serviceNow'] ||= {}
|
116
|
+
params['serviceNow']['closeIncidentAction'] = val
|
117
|
+
end
|
118
|
+
opts.on("--service-now-info-mapping low|medium|high", String, "ServiceNow: Info Mapping") do |val|
|
119
|
+
# allowed_values = 'low|medium|high'.split('|') # get_service_now_mappings().keys
|
120
|
+
# if !allowed_values.include?(val)
|
121
|
+
# raise ::OptionParser::InvalidOption.new("Info Mapping value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
|
122
|
+
# end
|
123
|
+
params['serviceNow'] ||= {}
|
124
|
+
params['serviceNow']['infoMapping'] = val
|
125
|
+
end
|
126
|
+
opts.on("--service-now-warning-mapping low|medium|high", String, "ServiceNow: Warning Mapping") do |val|
|
127
|
+
# allowed_values = 'low|medium|high'.split('|') # get_service_now_mappings().keys
|
128
|
+
# if !allowed_values.include?(val)
|
129
|
+
# raise ::OptionParser::InvalidOption.new("Warning Info Mapping value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
|
130
|
+
# end
|
131
|
+
params['serviceNow'] ||= {}
|
132
|
+
params['serviceNow']['warningMapping'] = val
|
133
|
+
end
|
134
|
+
opts.on("--service-now-critical-mapping low|medium|high", String, "ServiceNow: Critical Mapping") do |val|
|
135
|
+
# allowed_values = 'low|medium|high'.split('|') # get_service_now_mappings().keys
|
136
|
+
# if !allowed_values.include?(val)
|
137
|
+
# raise ::OptionParser::InvalidOption.new("Critical Info Mapping value '#{val}' is invalid.\nThe allowed values are: #{allowed_values.join(', ')}")
|
138
|
+
# end
|
139
|
+
params['serviceNow'] ||= {}
|
140
|
+
params['serviceNow']['criticalMapping'] = val
|
141
|
+
end
|
142
|
+
opts.on('--new-relic-enabled [on|off]', String, "New Relic: Enabled (on) or disabled (off)") do |val|
|
143
|
+
params['newRelic'] ||= {}
|
144
|
+
params['newRelic']['enabled'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
145
|
+
end
|
146
|
+
opts.on("--new-relic-license-key [VALUE]", String, "New Relic: License Key") do |val|
|
147
|
+
params['newRelic'] ||= {}
|
148
|
+
params['newRelic']['licenseKey'] = val
|
149
|
+
end
|
150
|
+
build_standard_update_options(opts, options)
|
151
|
+
opts.footer = "Update monitoring settings."
|
152
|
+
end
|
153
|
+
optparse.parse!(args)
|
154
|
+
connect(options)
|
155
|
+
verify_args!(args:args, optparse:optparse, count:0)
|
156
|
+
payload = parse_payload(options)
|
157
|
+
if !payload
|
158
|
+
payload = {}
|
159
|
+
payload.deep_merge!({object_key => parse_passed_options(options)}) # inject options passed with -O foo=bar
|
160
|
+
if params['serviceNow'] && params['serviceNow']['integration']
|
161
|
+
integration = find_by_name_or_id(:integration, params['serviceNow']['integration'])
|
162
|
+
if integration.nil?
|
163
|
+
exit 1 #return 1, "Integration not found by '#{options[:servicenow_integration]}'"
|
164
|
+
else
|
165
|
+
if integration['integrationType']['code'] != 'serviceNow'
|
166
|
+
raise_command_error "Integration '#{integration['id']}' must be a Service Now integration"
|
167
|
+
end
|
168
|
+
params['serviceNow'] ||= {}
|
169
|
+
params['serviceNow']['integration'] = {'id' => integration['id'].to_i}
|
170
|
+
end
|
171
|
+
end
|
172
|
+
payload.deep_merge!({object_key => params})
|
173
|
+
end
|
174
|
+
if payload[object_key].empty?
|
175
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
176
|
+
end
|
177
|
+
@monitoring_settings_interface.setopts(options)
|
178
|
+
if options[:dry_run]
|
179
|
+
print_dry_run @monitoring_settings_interface.dry.update(payload)
|
180
|
+
return
|
181
|
+
end
|
182
|
+
json_response = @monitoring_settings_interface.update(payload)
|
183
|
+
exit_code, err = 0, nil
|
184
|
+
render_response(json_response, options, object_key) do
|
185
|
+
if json_response['success']
|
186
|
+
print_green_success "Updated monitoring settings"
|
187
|
+
get([] + (options[:remote] ? ["-r",options[:remote]] : []))
|
188
|
+
else
|
189
|
+
exit_code, err = 1, "Error updating monitoring settings: #{json_response['msg'] || json_response['errors']}"
|
190
|
+
print_rest_errors(json_response)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
return exit_code, err
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def get_service_now_actions()
|
199
|
+
{
|
200
|
+
'create' => 'Create new incident in ServiceNow',
|
201
|
+
'close' => 'Resolve Incident in ServiceNow',
|
202
|
+
'activity' => 'Add Activity to Incident in ServiceNow',
|
203
|
+
'none' => 'No action',
|
204
|
+
}
|
205
|
+
end
|
206
|
+
|
207
|
+
def format_service_now_action(action_value)
|
208
|
+
get_service_now_actions()[action_value].to_s
|
209
|
+
end
|
210
|
+
|
211
|
+
def get_service_now_mappings()
|
212
|
+
{
|
213
|
+
'low' => 'Low',
|
214
|
+
'medium' => 'Medium',
|
215
|
+
'high' => 'High',
|
216
|
+
}
|
217
|
+
end
|
218
|
+
|
219
|
+
def format_service_now_mapping(mapping_value)
|
220
|
+
get_service_now_mappings()[mapping_value].to_s
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
def object_key
|
225
|
+
'monitoringSettings'
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|