morpheus-cli 3.1.2.1 → 3.2.0
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/lib/morpheus/api/api_client.rb +6 -2
- data/lib/morpheus/api/license_interface.rb +7 -0
- data/lib/morpheus/api/monitoring_apps_interface.rb +15 -2
- data/lib/morpheus/api/{checks_interface.rb → monitoring_checks_interface.rb} +8 -21
- data/lib/morpheus/api/monitoring_groups_interface.rb +23 -2
- data/lib/morpheus/api/{incidents_interface.rb → monitoring_incidents_interface.rb} +5 -5
- data/lib/morpheus/api/monitoring_interface.rb +4 -4
- data/lib/morpheus/api/user_groups_interface.rb +65 -0
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/cli/curl_command.rb +9 -7
- data/lib/morpheus/cli/dot_file.rb +11 -5
- data/lib/morpheus/cli/echo_command.rb +27 -3
- data/lib/morpheus/cli/license.rb +109 -20
- data/lib/morpheus/cli/login.rb +2 -0
- data/lib/morpheus/cli/logout.rb +2 -0
- data/lib/morpheus/cli/mixins/monitoring_helper.rb +97 -37
- data/lib/morpheus/cli/mixins/print_helper.rb +5 -2
- data/lib/morpheus/cli/monitoring_apps_command.rb +564 -9
- data/lib/morpheus/cli/monitoring_checks_command.rb +326 -93
- data/lib/morpheus/cli/monitoring_contacts_command.rb +2 -2
- data/lib/morpheus/cli/monitoring_groups_command.rb +540 -10
- data/lib/morpheus/cli/monitoring_incidents_command.rb +88 -56
- data/lib/morpheus/cli/remote.rb +6 -0
- data/lib/morpheus/cli/roles.rb +1 -1
- data/lib/morpheus/cli/set_prompt_command.rb +1 -0
- data/lib/morpheus/cli/shell.rb +17 -8
- data/lib/morpheus/cli/user_groups_command.rb +574 -0
- data/lib/morpheus/cli/users.rb +221 -115
- data/lib/morpheus/cli/version.rb +1 -1
- data/morpheus-cli.gemspec +1 -2
- metadata +11 -8
data/lib/morpheus/cli/login.rb
CHANGED
@@ -75,6 +75,8 @@ class Morpheus::Cli::Login
|
|
75
75
|
# check to see if we got credentials, or just look at login_result above...
|
76
76
|
creds = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials() # .load_saved_credentials(true)
|
77
77
|
|
78
|
+
# recalcuate echo vars
|
79
|
+
Morpheus::Cli::Echo.recalculate_variable_map()
|
78
80
|
# recalculate shell prompt after this change
|
79
81
|
if Morpheus::Cli::Shell.instance
|
80
82
|
Morpheus::Cli::Shell.instance.reinitialize()
|
data/lib/morpheus/cli/logout.rb
CHANGED
@@ -60,6 +60,8 @@ class Morpheus::Cli::Logout
|
|
60
60
|
puts "#{cyan}Logged out of #{@appliance_name}. Goodbye.#{reset}"
|
61
61
|
end
|
62
62
|
end
|
63
|
+
# recalcuate echo vars
|
64
|
+
Morpheus::Cli::Echo.recalculate_variable_map()
|
63
65
|
# recalculate shell prompt after this change
|
64
66
|
if Morpheus::Cli::Shell.instance
|
65
67
|
Morpheus::Cli::Shell.instance.reinitialize()
|
@@ -206,62 +206,73 @@ module Morpheus::Cli::MonitoringHelper
|
|
206
206
|
|
207
207
|
# Checks
|
208
208
|
|
209
|
-
def format_monitoring_check_status(check, return_color=cyan)
|
210
|
-
#<morph:statusIcon unknown="${!check.lastRunDate}" muted="${!check.createIncident}" failure="${check.lastCheckStatus == 'error'}" health="${check.health}" class="pull-left"/>
|
209
|
+
def format_monitoring_check_status(check, include_msg=false, return_color=cyan)
|
211
210
|
out = ""
|
212
|
-
|
213
|
-
status_string = check['lastCheckStatus'].to_s
|
211
|
+
unknown = check['lastRunDate'].nil?
|
214
212
|
failure = check['lastCheckStatus'] == 'error'
|
215
|
-
health = check['health']
|
216
|
-
|
217
|
-
|
213
|
+
health = check['health']
|
214
|
+
muted = check['createIncident'] == false
|
215
|
+
status_string = check['lastCheckStatus'].to_s # null for groups, ignore?
|
216
|
+
|
217
|
+
if unknown
|
218
|
+
out << "#{white}UNKNOWN#{return_color}"
|
219
|
+
elsif failure || health == 0
|
220
|
+
if include_msg && check['lastError']
|
221
|
+
out << "#{red}ERROR - #{check['lastError']}#{return_color}"
|
222
|
+
else
|
223
|
+
out << "#{red}ERROR#{return_color}"
|
224
|
+
end
|
225
|
+
elsif health.to_i >= 10
|
226
|
+
out << "#{green}HEALTHY#{return_color}"
|
218
227
|
else
|
219
|
-
out << "#{
|
228
|
+
out << "#{yellow}WARNING#{return_color}"
|
220
229
|
end
|
221
230
|
if muted
|
222
|
-
out << "(
|
231
|
+
out << " (MUTED)"
|
223
232
|
end
|
224
233
|
out
|
225
234
|
end
|
226
235
|
|
227
236
|
def format_monitoring_check_last_metric(check)
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
237
|
+
if check['lastMetric']
|
238
|
+
metric_name = check['checkType'] ? check['checkType']['metricName'] : nil
|
239
|
+
if metric_name
|
240
|
+
"#{check['lastMetric']} #{metric_name}"
|
241
|
+
else
|
242
|
+
"#{check['lastMetric']}"
|
243
|
+
end
|
244
|
+
else
|
245
|
+
"N/A"
|
246
|
+
end
|
233
247
|
end
|
234
248
|
|
235
249
|
def format_monitoring_check_type(check)
|
236
|
-
#<td class="check-type-col"><div class="check-type-icon ${morph.checkTypeCode(id:check.checkTypeId, checkTypes:checkTypes)}"></div></td>
|
237
|
-
# return get_object_value(check, 'checkType.name') # this works too
|
238
250
|
out = ""
|
239
|
-
if check
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
251
|
+
if check['checkType']
|
252
|
+
if check['checkType']['code'] == 'mixedCheck' || check['checkType']['code'] == 'mixed'
|
253
|
+
out = check['checkType']["name"] || "Mixed"
|
254
|
+
else
|
255
|
+
out = check['checkType']["name"] || ""
|
256
|
+
end
|
245
257
|
end
|
246
|
-
out
|
258
|
+
out
|
247
259
|
end
|
248
260
|
|
249
|
-
def print_checks_table(
|
261
|
+
def print_checks_table(checks, opts={})
|
250
262
|
columns = [
|
251
263
|
{"ID" => lambda {|check| check['id'] } },
|
252
264
|
{"STATUS" => lambda {|check| format_monitoring_check_status(check) } },
|
253
265
|
{"NAME" => lambda {|check| check['name'] } },
|
254
|
-
{"TIME" => lambda {|check| format_local_dt(check['lastRunDate']) } },
|
266
|
+
{"TIME" => lambda {|check| check['lastRunDate'] ? format_local_dt(check['lastRunDate']) : "N/A" } },
|
255
267
|
{"AVAILABILITY" => {display_method: lambda {|check| check['availability'] ? "#{check['availability'].to_f.round(3).to_s}%" : "N/A"} }, justify: "center" },
|
256
268
|
{"RESPONSE TIME" => {display_method: lambda {|check| check['lastTimer'] ? "#{check['lastTimer']}ms" : "N/A" } }, justify: "center" },
|
257
|
-
{"LAST METRIC" => {display_method: lambda {|check| check
|
258
|
-
{"TYPE" =>
|
259
|
-
|
269
|
+
{"LAST METRIC" => {display_method: lambda {|check| format_monitoring_check_last_metric(check) } }, justify: "center" },
|
270
|
+
{"TYPE" => lambda {|check| format_monitoring_check_type(check) } },
|
260
271
|
]
|
261
272
|
if opts[:include_fields]
|
262
273
|
columns = opts[:include_fields]
|
263
274
|
end
|
264
|
-
print as_pretty_table(
|
275
|
+
print as_pretty_table(checks, columns, opts)
|
265
276
|
end
|
266
277
|
|
267
278
|
def print_check_history_table(history_items, opts={})
|
@@ -372,7 +383,7 @@ module Morpheus::Cli::MonitoringHelper
|
|
372
383
|
|
373
384
|
def find_check_group_by_name(name)
|
374
385
|
json_results = monitoring_interface.groups.list({name: name})
|
375
|
-
groups = json_results["
|
386
|
+
groups = json_results["checkGroups"]
|
376
387
|
if groups.empty?
|
377
388
|
print_red_alert "Check Group not found by name #{name}"
|
378
389
|
exit 1 # return nil
|
@@ -388,20 +399,37 @@ module Morpheus::Cli::MonitoringHelper
|
|
388
399
|
end
|
389
400
|
end
|
390
401
|
|
402
|
+
def print_check_groups_table(check_groups, opts={})
|
403
|
+
columns = [
|
404
|
+
{"ID" => lambda {|check| check['id'] } },
|
405
|
+
{"STATUS" => lambda {|check| format_monitoring_check_status(check) } },
|
406
|
+
{"NAME" => lambda {|check| check['name'] } },
|
407
|
+
{"TIME" => lambda {|check| check['lastRunDate'] ? format_local_dt(check['lastRunDate']) : "N/A" } },
|
408
|
+
{"AVAILABILITY" => {display_method: lambda {|check| check['availability'] ? "#{check['availability'].to_f.round(3).to_s}%" : "N/A"} }, justify: "center" },
|
409
|
+
{"RESPONSE TIME" => {display_method: lambda {|check| check['lastTimer'] ? "#{check['lastTimer']}ms" : "N/A" } }, justify: "center" },
|
410
|
+
# {"LAST METRIC" => {display_method: lambda {|check| format_monitoring_check_last_metric(check) } }, justify: "center" },
|
411
|
+
{"TYPE" => lambda {|check| format_monitoring_check_type(check) } },
|
412
|
+
]
|
413
|
+
if opts[:include_fields]
|
414
|
+
columns = opts[:include_fields]
|
415
|
+
end
|
416
|
+
print as_pretty_table(check_groups, columns, opts)
|
417
|
+
end
|
418
|
+
|
391
419
|
# Monitoring apps
|
392
420
|
|
393
|
-
def
|
421
|
+
def find_monitoring_app_by_name_or_id(val)
|
394
422
|
if val.to_s =~ /\A\d{1,}\Z/
|
395
|
-
return
|
423
|
+
return find_monitoring_app_by_id(val)
|
396
424
|
else
|
397
|
-
return
|
425
|
+
return find_monitoring_app_by_name(val)
|
398
426
|
end
|
399
427
|
end
|
400
428
|
|
401
|
-
def
|
429
|
+
def find_monitoring_app_by_id(id)
|
402
430
|
begin
|
403
431
|
json_response = monitoring_interface.apps.get(id.to_i)
|
404
|
-
return json_response[
|
432
|
+
return json_response["monitorApp"] || json_response["app"]
|
405
433
|
rescue RestClient::Exception => e
|
406
434
|
if e.response && e.response.code == 404
|
407
435
|
print_red_alert "Monitor App not found by id #{id}"
|
@@ -412,9 +440,9 @@ module Morpheus::Cli::MonitoringHelper
|
|
412
440
|
end
|
413
441
|
end
|
414
442
|
|
415
|
-
def
|
443
|
+
def find_monitoring_app_by_name(name)
|
416
444
|
json_results = monitoring_interface.apps.list({name: name})
|
417
|
-
apps = json_results["apps"]
|
445
|
+
apps = json_results["monitorApps"] || json_results["apps"]
|
418
446
|
if apps.empty?
|
419
447
|
print_red_alert "Monitor App not found by name #{name}"
|
420
448
|
exit 1 # return nil
|
@@ -430,5 +458,37 @@ module Morpheus::Cli::MonitoringHelper
|
|
430
458
|
end
|
431
459
|
end
|
432
460
|
|
461
|
+
def print_monitoring_apps_table(apps, opts={})
|
462
|
+
columns = [
|
463
|
+
{"ID" => lambda {|app| app['id'] } },
|
464
|
+
{"STATUS" => lambda {|app| format_monitoring_check_status(app) } },
|
465
|
+
{"NAME" => lambda {|app| app['name'] } },
|
466
|
+
# {"DESCRIPTION" => lambda {|app| app['description'] } },
|
467
|
+
{"TIME" => lambda {|app| app['lastRunDate'] ? format_local_dt(app['lastRunDate']) : "N/A" } },
|
468
|
+
{"AVAILABILITY" => {display_method: lambda {|app| app['availability'] ? "#{app['availability'].to_f.round(3).to_s}%" : "N/A"} }, justify: "center" },
|
469
|
+
{"RESPONSE TIME" => {display_method: lambda {|app| app['lastTimer'] ? "#{app['lastTimer']}ms" : "N/A" } }, justify: "center" },
|
470
|
+
#{"LAST METRIC" => {display_method: lambda {|app| app['lastMetric'] ? "#{app['lastMetric']}" : "N/A" } }, justify: "center" },
|
471
|
+
{"CHECKS" => lambda {|app|
|
472
|
+
checks = app['checks']
|
473
|
+
checks_str = ""
|
474
|
+
if checks && checks.size > 0
|
475
|
+
checks_str = "#{checks.size} #{checks.size == 1 ? 'check' : 'checks'}"
|
476
|
+
# checks_str << " [#{checks.join(', ')}]"
|
477
|
+
end
|
478
|
+
check_groups = app['checkGroups']
|
479
|
+
check_groups_str = ""
|
480
|
+
if check_groups && check_groups.size > 0
|
481
|
+
check_groups_str = "#{check_groups.size} #{check_groups.size == 1 ? 'group' : 'groups'}"
|
482
|
+
# check_groups_str << " [#{check_groups.join(', ')}]"
|
483
|
+
end
|
484
|
+
[checks_str, check_groups_str].reject {|s| s.empty? }.join(", ")
|
485
|
+
} },
|
486
|
+
|
487
|
+
]
|
488
|
+
if opts[:include_fields]
|
489
|
+
columns = opts[:include_fields]
|
490
|
+
end
|
491
|
+
print as_pretty_table(apps, columns, opts)
|
492
|
+
end
|
433
493
|
|
434
494
|
end
|
@@ -753,9 +753,9 @@ module Morpheus::Cli::PrintHelper
|
|
753
753
|
# if include_fields
|
754
754
|
# json_fields_for = options[:json_fields_for] || options[:fields_for] || options[:root_field]
|
755
755
|
# if json_fields_for && data[json_fields_for]
|
756
|
-
# data[json_fields_for] =
|
756
|
+
# data[json_fields_for] = filter_data(data[json_fields_for], include_fields)
|
757
757
|
# else
|
758
|
-
# data =
|
758
|
+
# data = filter_data(data, include_fields)
|
759
759
|
# end
|
760
760
|
# end
|
761
761
|
do_pretty = options.key?(:pretty_json) ? options[:pretty_json] : true
|
@@ -783,6 +783,9 @@ module Morpheus::Cli::PrintHelper
|
|
783
783
|
if !data
|
784
784
|
return "null" # "No data"
|
785
785
|
end
|
786
|
+
# if opts[:include_fields]
|
787
|
+
# data = filter_data(data, opts[:include_fields])
|
788
|
+
# end
|
786
789
|
begin
|
787
790
|
out << data.to_yaml
|
788
791
|
rescue => err
|
@@ -5,15 +5,10 @@ class Morpheus::Cli::MonitoringAppsCommand
|
|
5
5
|
include Morpheus::Cli::CliCommand
|
6
6
|
include Morpheus::Cli::MonitoringHelper
|
7
7
|
|
8
|
-
set_command_name :'
|
9
|
-
register_subcommands :list, :get, :add, :update, :remove, :quarantine, :history, :statistics
|
10
|
-
set_default_subcommand :list
|
11
|
-
|
12
|
-
set_command_hidden # remove me when implemented
|
8
|
+
set_command_name :'monitor-apps'
|
13
9
|
|
14
|
-
|
15
|
-
|
16
|
-
end
|
10
|
+
register_subcommands :list, :get, :add, :update, :remove
|
11
|
+
register_subcommands :mute, :unmute #, :history, :statistics
|
17
12
|
|
18
13
|
def connect(opts)
|
19
14
|
@api_client = establish_remote_appliance_connection(opts)
|
@@ -24,6 +19,566 @@ class Morpheus::Cli::MonitoringAppsCommand
|
|
24
19
|
handle_subcommand(args)
|
25
20
|
end
|
26
21
|
|
27
|
-
|
22
|
+
def list(args)
|
23
|
+
options = {}
|
24
|
+
params = {}
|
25
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
26
|
+
opts.banner = subcommand_usage()
|
27
|
+
opts.on('--status LIST', Array, "Filter by status. error,healthy,warning,muted") do |list|
|
28
|
+
params['status'] = list
|
29
|
+
end
|
30
|
+
build_common_options(opts, options, [:list, :last_updated, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
31
|
+
end
|
32
|
+
optparse.parse!(args)
|
33
|
+
connect(options)
|
34
|
+
begin
|
35
|
+
[:phrase, :offset, :max, :sort, :direction, :lastUpdated].each do |k|
|
36
|
+
params[k] = options[k] unless options[k].nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
if options[:dry_run]
|
40
|
+
print_dry_run @monitoring_interface.apps.dry.list(params)
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
json_response = @monitoring_interface.apps.list(params)
|
45
|
+
if options[:include_fields]
|
46
|
+
json_response = {"monitorApps" => filter_data(json_response["monitorApps"], options[:include_fields]) }
|
47
|
+
end
|
48
|
+
if options[:json]
|
49
|
+
puts as_json(json_response, options)
|
50
|
+
return 0
|
51
|
+
elsif options[:csv]
|
52
|
+
puts records_as_csv(json_response['monitorApps'], options)
|
53
|
+
return 0
|
54
|
+
elsif options[:yaml]
|
55
|
+
puts as_yaml(json_response, options)
|
56
|
+
return 0
|
57
|
+
end
|
58
|
+
monitor_apps = json_response['monitorApps']
|
59
|
+
title = "Morpheus Monitoring Apps"
|
60
|
+
subtitles = []
|
61
|
+
# if app
|
62
|
+
# subtitles << "App: #{app['name']}".strip
|
63
|
+
# end
|
64
|
+
# if cloud
|
65
|
+
# subtitles << "Cloud: #{cloud['name']}".strip
|
66
|
+
# end
|
67
|
+
if params[:phrase]
|
68
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
69
|
+
end
|
70
|
+
print_h1 title, subtitles
|
71
|
+
if monitor_apps.empty?
|
72
|
+
print cyan,"No monitoring apps found.",reset,"\n"
|
73
|
+
else
|
74
|
+
print_monitoring_apps_table(monitor_apps, options)
|
75
|
+
print_results_pagination(json_response, {:label => "monitoring app", :n_label => "monitoring apps"})
|
76
|
+
# print_results_pagination(json_response)
|
77
|
+
end
|
78
|
+
print reset,"\n"
|
79
|
+
rescue RestClient::Exception => e
|
80
|
+
print_rest_exception(e, options)
|
81
|
+
exit 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def get(args)
|
86
|
+
options = {}
|
87
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
88
|
+
opts.banner = subcommand_usage("[id list]")
|
89
|
+
opts.on(nil,'--history', "Display Monitoring App History") do |val|
|
90
|
+
options[:show_history] = true
|
91
|
+
end
|
92
|
+
# opts.on(nil,'--statistics', "Display Statistics") do |val|
|
93
|
+
# options[:show_statistics] = true
|
94
|
+
# end
|
95
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
96
|
+
end
|
97
|
+
optparse.parse!(args)
|
98
|
+
if args.count < 1
|
99
|
+
puts optparse
|
100
|
+
exit 1
|
101
|
+
end
|
102
|
+
connect(options)
|
103
|
+
id_list = parse_id_list(args)
|
104
|
+
return run_command_for_each_arg(id_list) do |arg|
|
105
|
+
_get(arg, options)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def _get(id, options)
|
110
|
+
|
111
|
+
begin
|
112
|
+
monitor_app = find_monitoring_app_by_name_or_id(id)
|
113
|
+
|
114
|
+
if options[:dry_run]
|
115
|
+
print_dry_run @monitoring_interface.apps.dry.get(monitor_app['id'])
|
116
|
+
return
|
117
|
+
end
|
118
|
+
json_response = @monitoring_interface.apps.get(monitor_app['id'])
|
119
|
+
monitor_app = json_response['monitorApp']
|
120
|
+
if options[:include_fields]
|
121
|
+
json_response = {"monitorApp" => filter_data(json_response["monitorApp"], options[:include_fields]) }
|
122
|
+
end
|
123
|
+
if options[:json]
|
124
|
+
puts as_json(json_response, options)
|
125
|
+
return 0
|
126
|
+
elsif options[:yaml]
|
127
|
+
puts as_yaml(json_response, options)
|
128
|
+
return 0
|
129
|
+
elsif options[:csv]
|
130
|
+
puts records_as_csv([json_response['monitorApp']], options)
|
131
|
+
return 0
|
132
|
+
end
|
133
|
+
|
134
|
+
print_h1 "Monitoring App Details"
|
135
|
+
print cyan
|
136
|
+
description_cols = {
|
137
|
+
"ID" => lambda {|it| it['id'] },
|
138
|
+
"Status" => lambda {|it| format_monitoring_check_status(it, true) },
|
139
|
+
"Name" => lambda {|it| it['name'] },
|
140
|
+
"Description" => lambda {|it| it['description'] },
|
141
|
+
"Time" => lambda {|it| format_local_dt(it['lastRunDate']) },
|
142
|
+
"Availability" => lambda {|it| it['availability'] ? "#{it['availability'].to_f.round(3).to_s}%" : "N/A"},
|
143
|
+
"Response Time" => lambda {|it| it['lastTimer'] ? "#{it['lastTimer']}ms" : "N/A" }
|
144
|
+
}
|
145
|
+
print_description_list(description_cols, monitor_app)
|
146
|
+
|
147
|
+
## Chart Stats
|
148
|
+
|
149
|
+
|
150
|
+
## Checks in this app
|
151
|
+
checks = json_response["checks"]
|
152
|
+
if checks && !checks.empty?
|
153
|
+
print_h2 "Checks"
|
154
|
+
print_checks_table(checks, options)
|
155
|
+
else
|
156
|
+
# print "\n"
|
157
|
+
# puts "No checks in this monitoring app"
|
158
|
+
end
|
159
|
+
|
160
|
+
## Check Groups in this app
|
161
|
+
check_groups = json_response["checkGroups"]
|
162
|
+
if check_groups && !check_groups.empty?
|
163
|
+
print_h2 "Groups"
|
164
|
+
print_check_groups_table(check_groups, options)
|
165
|
+
else
|
166
|
+
# print "\n"
|
167
|
+
# puts "No check groups in this monitoring app"
|
168
|
+
end
|
169
|
+
|
170
|
+
## Open Incidents
|
171
|
+
open_incidents = json_response["openIncidents"]
|
172
|
+
if open_incidents && !open_incidents.empty?
|
173
|
+
print_h2 "Open Incidents"
|
174
|
+
# puts "\n(table coming soon...)\n"
|
175
|
+
puts JSON.pretty_generate(open_incidents)
|
176
|
+
# todo: move this to MonitoringHelper ?
|
177
|
+
# print_incidents_table(issues, options)
|
178
|
+
else
|
179
|
+
print "\n", cyan
|
180
|
+
puts "No open incidents for this monitoring app"
|
181
|
+
end
|
182
|
+
|
183
|
+
## History (plain old Hash)
|
184
|
+
if options[:show_history]
|
185
|
+
# history_items = json_response["history"]
|
186
|
+
# gotta go get it
|
187
|
+
history_json_response = @monitoring_interface.apps.history(monitor_app["id"], {})
|
188
|
+
history_items = history_json_response["history"] || history_json_response["events"] || history_json_response["issues"]
|
189
|
+
issues = history_items
|
190
|
+
if history_items && !history_items.empty?
|
191
|
+
print_h2 "History"
|
192
|
+
print_check_history_table(history_items, options)
|
193
|
+
print_results_pagination(history_json_response, {:label => "event", :n_label => "events"})
|
194
|
+
else
|
195
|
+
print "\n"
|
196
|
+
puts "No history found for this monitoring app"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
## Statistics (Hash)
|
201
|
+
if options[:show_statistics]
|
202
|
+
# todo....
|
203
|
+
end
|
204
|
+
|
205
|
+
print reset,"\n"
|
206
|
+
|
207
|
+
rescue RestClient::Exception => e
|
208
|
+
print_rest_exception(e, options)
|
209
|
+
exit 1
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def history(args)
|
214
|
+
options = {}
|
215
|
+
params = {}
|
216
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
217
|
+
opts.banner = subcommand_usage("[name] [options]")
|
218
|
+
# opts.on('--status LIST', Array, "Filter by status. open, closed") do |list|
|
219
|
+
# params['status'] = list
|
220
|
+
# end
|
221
|
+
opts.on('--severity LIST', Array, "Filter by severity. critical, warning, info") do |list|
|
222
|
+
params['severity'] = list
|
223
|
+
end
|
224
|
+
build_common_options(opts, options, [:list, :last_updated, :json, :yaml, :csv, :fields, :json, :dry_run, :remote])
|
225
|
+
end
|
226
|
+
optparse.parse!(args)
|
227
|
+
if args.count < 1
|
228
|
+
puts optparse
|
229
|
+
exit 1
|
230
|
+
end
|
231
|
+
connect(options)
|
232
|
+
begin
|
233
|
+
monitor_app = find_monitoring_app_by_name_or_id(args[0])
|
234
|
+
return 1 if monitor_app.nil?
|
235
|
+
|
236
|
+
[:phrase, :offset, :max, :sort, :direction, :lastUpdated].each do |k|
|
237
|
+
params[k] = options[k] unless options[k].nil?
|
238
|
+
end
|
239
|
+
# JD: lastUpdated 500ing, checks don't have that property ? =o Fix it!
|
240
|
+
|
241
|
+
if options[:dry_run]
|
242
|
+
print_dry_run @monitoring_interface.apps.dry.history(monitor_app['id'], params)
|
243
|
+
return
|
244
|
+
end
|
245
|
+
|
246
|
+
json_response = @monitoring_interface.apps.history(monitor_app['id'], params)
|
247
|
+
if options[:json]
|
248
|
+
if options[:include_fields]
|
249
|
+
json_response = {"history" => filter_data(json_response["history"], options[:include_fields]) }
|
250
|
+
end
|
251
|
+
puts as_json(json_response, options)
|
252
|
+
return 0
|
253
|
+
end
|
254
|
+
if options[:csv]
|
255
|
+
puts records_as_csv(json_response['history'], options)
|
256
|
+
return 0
|
257
|
+
end
|
258
|
+
history_items = json_response['history']
|
259
|
+
title = "Monitoring App History: #{monitor_app['name']}"
|
260
|
+
subtitles = []
|
261
|
+
if params[:phrase]
|
262
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
263
|
+
end
|
264
|
+
print_h1 title, subtitles
|
265
|
+
if history_items.empty?
|
266
|
+
print cyan,"No history found.",reset,"\n"
|
267
|
+
else
|
268
|
+
print_check_history_table(history_items, options)
|
269
|
+
print_results_pagination(json_response, {:label => "event", :n_label => "events"})
|
270
|
+
end
|
271
|
+
print reset,"\n"
|
272
|
+
rescue RestClient::Exception => e
|
273
|
+
print_rest_exception(e, options)
|
274
|
+
exit 1
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def add(args)
|
279
|
+
options = {}
|
280
|
+
params = {'inUptime' => true, 'severity' => 'critical'}
|
281
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
282
|
+
opts.banner = subcommand_usage("[name]")
|
283
|
+
opts.on('--name VALUE', String, "Name") do |val|
|
284
|
+
params['name'] = val
|
285
|
+
end
|
286
|
+
opts.on('--description VALUE', String, "Description") do |val|
|
287
|
+
params['description'] = val
|
288
|
+
end
|
289
|
+
opts.on('--minHappy VALUE', String, "Min Checks. This specifies the minimum number of checks within the app that must be happy to keep the app from becoming unhealthy.") do |val|
|
290
|
+
params['minHappy'] = val.to_i
|
291
|
+
end
|
292
|
+
opts.on('--severity VALUE', String, "Max Severity. Determines the maximum severity level this app can incur on an incident when failing. Default is critical") do |val|
|
293
|
+
params['severity'] = val
|
294
|
+
end
|
295
|
+
opts.on('--inUptime [on|off]', String, "Affects Availability. Default is on.") do |val|
|
296
|
+
params['inUptime'] = val.nil? || val.to_s == 'on' || val.to_s == 'true'
|
297
|
+
end
|
298
|
+
opts.on('--checks LIST', Array, "Checks to include in this app, comma separated list of IDs") do |list|
|
299
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
300
|
+
params['checks'] = []
|
301
|
+
else
|
302
|
+
params['checks'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
303
|
+
end
|
304
|
+
end
|
305
|
+
opts.on('--checkGroups LIST', Array, "Check Groups to include in this app, comma separated list of IDs") do |list|
|
306
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
307
|
+
params['checkGroups'] = []
|
308
|
+
else
|
309
|
+
params['checkGroups'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
310
|
+
end
|
311
|
+
end
|
312
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote, :quiet])
|
313
|
+
opts.footer = "Create a new app of monitoring checks." + "\n" +
|
314
|
+
"[name] is required and can be passed as --name instead."
|
315
|
+
end
|
316
|
+
optparse.parse!(args)
|
317
|
+
if args.count > 1
|
318
|
+
print_error Morpheus::Terminal.angry_prompt
|
319
|
+
puts_error "wrong number of arguments, expected 0-1 and got #{args.count}\n#{optparse}"
|
320
|
+
return 1
|
321
|
+
end
|
322
|
+
# support [name] as first argument
|
323
|
+
if args[0]
|
324
|
+
params['name'] = args[0]
|
325
|
+
end
|
326
|
+
connect(options)
|
327
|
+
begin
|
328
|
+
# construct payload
|
329
|
+
payload = nil
|
330
|
+
if options[:payload]
|
331
|
+
payload = options[:payload]
|
332
|
+
else
|
333
|
+
# merge -O options into normally parsed options
|
334
|
+
params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
335
|
+
if params['checks']
|
336
|
+
params['checks'] = params['checks'].collect {|it| it.to_i }
|
337
|
+
end
|
338
|
+
if params['checkGroups']
|
339
|
+
params['checkGroups'] = params['checkGroups'].collect {|it| it.to_i }
|
340
|
+
end
|
341
|
+
# todo: prompt?
|
342
|
+
payload = {'monitorApp' => params}
|
343
|
+
end
|
344
|
+
if options[:dry_run]
|
345
|
+
print_dry_run @monitoring_interface.apps.dry.create(payload)
|
346
|
+
return
|
347
|
+
end
|
348
|
+
json_response = @monitoring_interface.apps.create(payload)
|
349
|
+
if options[:json]
|
350
|
+
puts as_json(json_response, options)
|
351
|
+
elsif !options[:quiet]
|
352
|
+
monitor_app = json_response['monitorApp']
|
353
|
+
print_green_success "Added monitoring app #{monitor_app['name']}"
|
354
|
+
_get(monitor_app['id'], {})
|
355
|
+
end
|
356
|
+
return 0
|
357
|
+
rescue RestClient::Exception => e
|
358
|
+
print_rest_exception(e, options)
|
359
|
+
exit 1
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
def update(args)
|
364
|
+
options = {}
|
365
|
+
params = {}
|
366
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
367
|
+
opts.banner = subcommand_usage("[name]")
|
368
|
+
opts.on('--name VALUE', String, "Name") do |val|
|
369
|
+
params['name'] = val
|
370
|
+
end
|
371
|
+
opts.on('--description VALUE', String, "Description") do |val|
|
372
|
+
params['description'] = val
|
373
|
+
end
|
374
|
+
opts.on('--minHappy VALUE', String, "Min Checks. This specifies the minimum number of checks within the app that must be happy to keep the app from becoming unhealthy.") do |val|
|
375
|
+
params['minHappy'] = val.to_i
|
376
|
+
end
|
377
|
+
opts.on('--severity VALUE', String, "Max Severity. Determines the maximum severity level this app can incur on an incident when failing. Default is critical") do |val|
|
378
|
+
params['severity'] = val
|
379
|
+
end
|
380
|
+
opts.on('--inUptime [on|off]', String, "Affects Availability. Default is on.") do |val|
|
381
|
+
params['inUptime'] = val.nil? || val.to_s == 'on' || val.to_s == 'true'
|
382
|
+
end
|
383
|
+
opts.on('--checks LIST', Array, "Checks to include in this app, comma separated list of IDs") do |list|
|
384
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
385
|
+
params['checks'] = []
|
386
|
+
else
|
387
|
+
params['checks'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
388
|
+
end
|
389
|
+
end
|
390
|
+
opts.on('--checkGroups LIST', Array, "Check Groups to include in this app, comma separated list of IDs") do |list|
|
391
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
392
|
+
params['checkGroups'] = []
|
393
|
+
else
|
394
|
+
params['checkGroups'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
395
|
+
end
|
396
|
+
end
|
397
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote, :quiet])
|
398
|
+
opts.footer = "Update a monitoring app." + "\n" +
|
399
|
+
"[name] is required. This is the name or id of a monitoring app."
|
400
|
+
end
|
401
|
+
optparse.parse!(args)
|
402
|
+
if args.count != 1
|
403
|
+
print_error Morpheus::Terminal.angry_prompt
|
404
|
+
puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
|
405
|
+
return 1
|
406
|
+
end
|
407
|
+
connect(options)
|
408
|
+
begin
|
409
|
+
monitor_app = find_monitoring_app_by_name_or_id(args[0])
|
410
|
+
# construct payload
|
411
|
+
payload = nil
|
412
|
+
if options[:payload]
|
413
|
+
payload = options[:payload]
|
414
|
+
else
|
415
|
+
# merge -O options into normally parsed options
|
416
|
+
params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
417
|
+
if params['checks']
|
418
|
+
params['checks'] = params['checks'].collect {|it| it.to_i }
|
419
|
+
end
|
420
|
+
if params['checkGroups']
|
421
|
+
params['checkGroups'] = params['checkGroups'].collect {|it| it.to_i }
|
422
|
+
end
|
423
|
+
# todo: prompt?
|
424
|
+
payload = {'monitorApp' => params}
|
425
|
+
end
|
426
|
+
if options[:dry_run]
|
427
|
+
print_dry_run @monitoring_interface.apps.dry.update(monitor_app["id"], payload)
|
428
|
+
return
|
429
|
+
end
|
430
|
+
json_response = @monitoring_interface.apps.update(monitor_app["id"], payload)
|
431
|
+
if options[:json]
|
432
|
+
puts as_json(json_response, options)
|
433
|
+
elsif !options[:quiet]
|
434
|
+
print_green_success "Updated monitoring app #{monitor_app['name']}"
|
435
|
+
_get(monitor_app['id'], {})
|
436
|
+
end
|
437
|
+
return 0
|
438
|
+
rescue RestClient::Exception => e
|
439
|
+
print_rest_exception(e, options)
|
440
|
+
exit 1
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
def mute(args)
|
445
|
+
options = {}
|
446
|
+
params = {'enabled' => true}
|
447
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
448
|
+
opts.banner = subcommand_usage("[name]")
|
449
|
+
opts.on(nil, "--disable", "Unmute instead, the same as the unmute command") do
|
450
|
+
params['enabled'] = false
|
451
|
+
end
|
452
|
+
opts.footer = "Mute a monitoring app. This prevents it from creating new incidents." + "\n" +
|
453
|
+
"[name] is required. This is the name or id of a monitoring app."
|
454
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote, :quiet])
|
455
|
+
end
|
456
|
+
optparse.parse!(args)
|
457
|
+
if args.count < 1
|
458
|
+
puts optparse
|
459
|
+
exit 1
|
460
|
+
end
|
461
|
+
connect(options)
|
462
|
+
begin
|
463
|
+
monitor_app = find_monitoring_app_by_name_or_id(args[0])
|
464
|
+
# construct payload
|
465
|
+
payload = nil
|
466
|
+
if options[:payload]
|
467
|
+
payload = options[:payload]
|
468
|
+
else
|
469
|
+
payload = params
|
470
|
+
end
|
471
|
+
if options[:dry_run]
|
472
|
+
print_dry_run @monitoring_interface.apps.dry.quarantine(monitor_app["id"], payload)
|
473
|
+
return 0
|
474
|
+
end
|
475
|
+
json_response = @monitoring_interface.apps.quarantine(monitor_app["id"], payload)
|
476
|
+
if options[:json]
|
477
|
+
puts as_json(json_response, options)
|
478
|
+
elsif !options[:quiet]
|
479
|
+
if params['enabled']
|
480
|
+
print_green_success "Muted app #{monitor_app['name']}"
|
481
|
+
else
|
482
|
+
print_green_success "Unmuted app #{monitor_app['name']}"
|
483
|
+
end
|
484
|
+
_get(monitor_app['id'], {})
|
485
|
+
end
|
486
|
+
return 0
|
487
|
+
rescue RestClient::Exception => e
|
488
|
+
print_rest_exception(e, options)
|
489
|
+
exit 1
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
def unmute(args)
|
494
|
+
options = {}
|
495
|
+
params = {'enabled' => false}
|
496
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
497
|
+
opts.banner = subcommand_usage("[name]")
|
498
|
+
build_common_options(opts, options, [:payload, :json, :dry_run, :remote, :quiet])
|
499
|
+
opts.footer = "Unmute a monitoring app." + "\n" +
|
500
|
+
"[name] is required. This is the name or id of a monitoring app."
|
501
|
+
end
|
502
|
+
optparse.parse!(args)
|
503
|
+
if args.count < 1
|
504
|
+
puts optparse
|
505
|
+
exit 1
|
506
|
+
end
|
507
|
+
connect(options)
|
508
|
+
|
509
|
+
begin
|
510
|
+
monitor_app = find_monitoring_app_by_name_or_id(args[0])
|
511
|
+
# construct payload
|
512
|
+
payload = nil
|
513
|
+
if options[:payload]
|
514
|
+
payload = options[:payload]
|
515
|
+
else
|
516
|
+
payload = params
|
517
|
+
end
|
518
|
+
if options[:dry_run]
|
519
|
+
print_dry_run @monitoring_interface.apps.dry.quarantine(monitor_app["id"], payload)
|
520
|
+
return 0
|
521
|
+
end
|
522
|
+
json_response = @monitoring_interface.apps.quarantine(monitor_app["id"], payload)
|
523
|
+
if options[:json]
|
524
|
+
puts as_json(json_response, options)
|
525
|
+
elsif !options[:quiet]
|
526
|
+
print_green_success "Unmuted app #{monitor_app['name']}"
|
527
|
+
_get(monitor_app['id'], {})
|
528
|
+
end
|
529
|
+
return 0
|
530
|
+
rescue RestClient::Exception => e
|
531
|
+
print_rest_exception(e, options)
|
532
|
+
exit 1
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
def remove(args)
|
537
|
+
options = {}
|
538
|
+
params = {}
|
539
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
540
|
+
opts.banner = subcommand_usage("[name]")
|
541
|
+
build_common_options(opts, options, [:json, :dry_run, :quiet])
|
542
|
+
end
|
543
|
+
optparse.parse!(args)
|
544
|
+
if args.count < 1
|
545
|
+
puts optparse
|
546
|
+
return 127
|
547
|
+
end
|
548
|
+
connect(options)
|
549
|
+
|
550
|
+
begin
|
551
|
+
monitor_app = find_monitoring_app_by_name_or_id(args[0])
|
552
|
+
|
553
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to delete monitoring app '#{monitor_app['name']}'?", options)
|
554
|
+
return false
|
555
|
+
end
|
556
|
+
|
557
|
+
# payload = {
|
558
|
+
# 'monitorApp' => {id: monitor_app["id"]}
|
559
|
+
# }
|
560
|
+
# payload['monitorApp'].merge!(monitor_app)
|
561
|
+
payload = params
|
562
|
+
|
563
|
+
if options[:dry_run]
|
564
|
+
print_dry_run @monitoring_interface.apps.dry.destroy(monitor_app["id"])
|
565
|
+
return
|
566
|
+
end
|
567
|
+
|
568
|
+
json_response = @monitoring_interface.apps.destroy(monitor_app["id"])
|
569
|
+
if options[:json]
|
570
|
+
puts as_json(json_response, options)
|
571
|
+
elsif !options[:quiet]
|
572
|
+
print_green_success "Deleted check app #{monitor_app['name']}"
|
573
|
+
end
|
574
|
+
return 0, nil
|
575
|
+
rescue RestClient::Exception => e
|
576
|
+
print_rest_exception(e, options)
|
577
|
+
return 1
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
581
|
+
|
582
|
+
private
|
28
583
|
|
29
584
|
end
|