morpheus-cli 2.10.3 → 2.11.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/bin/morpheus +5 -96
- data/lib/morpheus/api/api_client.rb +23 -1
- data/lib/morpheus/api/checks_interface.rb +106 -0
- data/lib/morpheus/api/incidents_interface.rb +102 -0
- data/lib/morpheus/api/monitoring_apps_interface.rb +47 -0
- data/lib/morpheus/api/monitoring_contacts_interface.rb +47 -0
- data/lib/morpheus/api/monitoring_groups_interface.rb +47 -0
- data/lib/morpheus/api/monitoring_interface.rb +36 -0
- data/lib/morpheus/api/option_type_lists_interface.rb +47 -0
- data/lib/morpheus/api/option_types_interface.rb +47 -0
- data/lib/morpheus/api/roles_interface.rb +0 -1
- data/lib/morpheus/api/setup_interface.rb +19 -9
- data/lib/morpheus/cli.rb +20 -1
- data/lib/morpheus/cli/accounts.rb +8 -3
- data/lib/morpheus/cli/app_templates.rb +19 -11
- data/lib/morpheus/cli/apps.rb +52 -37
- data/lib/morpheus/cli/cli_command.rb +229 -53
- data/lib/morpheus/cli/cli_registry.rb +48 -40
- data/lib/morpheus/cli/clouds.rb +55 -26
- data/lib/morpheus/cli/command_error.rb +12 -0
- data/lib/morpheus/cli/credentials.rb +68 -26
- data/lib/morpheus/cli/curl_command.rb +98 -0
- data/lib/morpheus/cli/dashboard_command.rb +2 -7
- data/lib/morpheus/cli/deployments.rb +4 -4
- data/lib/morpheus/cli/deploys.rb +1 -2
- data/lib/morpheus/cli/dot_file.rb +5 -8
- data/lib/morpheus/cli/error_handler.rb +179 -15
- data/lib/morpheus/cli/groups.rb +21 -13
- data/lib/morpheus/cli/hosts.rb +220 -110
- data/lib/morpheus/cli/instance_types.rb +2 -2
- data/lib/morpheus/cli/instances.rb +257 -167
- data/lib/morpheus/cli/key_pairs.rb +15 -9
- data/lib/morpheus/cli/library.rb +673 -27
- data/lib/morpheus/cli/license.rb +2 -2
- data/lib/morpheus/cli/load_balancers.rb +4 -4
- data/lib/morpheus/cli/log_level_command.rb +6 -4
- data/lib/morpheus/cli/login.rb +17 -3
- data/lib/morpheus/cli/logout.rb +25 -11
- data/lib/morpheus/cli/man_command.rb +388 -0
- data/lib/morpheus/cli/mixins/accounts_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/monitoring_helper.rb +434 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +620 -112
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +1 -1
- data/lib/morpheus/cli/monitoring_apps_command.rb +29 -0
- data/lib/morpheus/cli/monitoring_checks_command.rb +427 -0
- data/lib/morpheus/cli/monitoring_contacts_command.rb +373 -0
- data/lib/morpheus/cli/monitoring_groups_command.rb +29 -0
- data/lib/morpheus/cli/monitoring_incidents_command.rb +711 -0
- data/lib/morpheus/cli/option_types.rb +10 -1
- data/lib/morpheus/cli/recent_activity_command.rb +2 -5
- data/lib/morpheus/cli/remote.rb +874 -134
- data/lib/morpheus/cli/roles.rb +54 -27
- data/lib/morpheus/cli/security_group_rules.rb +2 -2
- data/lib/morpheus/cli/security_groups.rb +23 -19
- data/lib/morpheus/cli/set_prompt_command.rb +50 -0
- data/lib/morpheus/cli/shell.rb +222 -157
- data/lib/morpheus/cli/tasks.rb +19 -15
- data/lib/morpheus/cli/users.rb +27 -17
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +28 -13
- data/lib/morpheus/cli/whoami.rb +131 -52
- data/lib/morpheus/cli/workflows.rb +24 -9
- data/lib/morpheus/formatters.rb +195 -3
- data/lib/morpheus/logging.rb +86 -0
- data/lib/morpheus/terminal.rb +371 -0
- data/scripts/generate_morpheus_commands_help.morpheus +60 -0
- metadata +21 -2
@@ -0,0 +1,373 @@
|
|
1
|
+
# require 'yaml'
|
2
|
+
require 'time'
|
3
|
+
require 'io/console'
|
4
|
+
require 'rest_client'
|
5
|
+
require 'optparse'
|
6
|
+
require 'filesize'
|
7
|
+
require 'table_print'
|
8
|
+
require 'morpheus/cli/cli_command'
|
9
|
+
require 'morpheus/cli/mixins/provisioning_helper'
|
10
|
+
|
11
|
+
class Morpheus::Cli::MonitorContactsCommand
|
12
|
+
include Morpheus::Cli::CliCommand
|
13
|
+
include Morpheus::Cli::MonitoringHelper
|
14
|
+
|
15
|
+
set_command_name :'monitoring-contacts'
|
16
|
+
|
17
|
+
register_subcommands :list, :get, :add, :update, :remove
|
18
|
+
|
19
|
+
def initialize()
|
20
|
+
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
21
|
+
end
|
22
|
+
|
23
|
+
def connect(opts)
|
24
|
+
@api_client = establish_remote_appliance_connection(opts)
|
25
|
+
@monitoring_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).monitoring
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle(args)
|
29
|
+
handle_subcommand(args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def list(args)
|
33
|
+
options = {}
|
34
|
+
params = {}
|
35
|
+
optparse = OptionParser.new do|opts|
|
36
|
+
opts.banner = subcommand_usage()
|
37
|
+
build_common_options(opts, options, [:list, :json, :csv, :fields, :json, :dry_run])
|
38
|
+
end
|
39
|
+
optparse.parse!(args)
|
40
|
+
connect(options)
|
41
|
+
begin
|
42
|
+
[:phrase, :offset, :max, :sort, :direction].each do |k|
|
43
|
+
params[k] = options[k] unless options[k].nil?
|
44
|
+
end
|
45
|
+
# JD: lastUpdated 500ing, contacts don't have that property ? =o Fix it!
|
46
|
+
|
47
|
+
if options[:dry_run]
|
48
|
+
print_dry_run @monitoring_interface.contacts.dry.list(params)
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
json_response = @monitoring_interface.contacts.list(params)
|
53
|
+
if options[:json]
|
54
|
+
if options[:include_fields]
|
55
|
+
json_response = {"contacts" => filter_data(json_response["contacts"], options[:include_fields]) }
|
56
|
+
end
|
57
|
+
puts as_json(json_response, options)
|
58
|
+
return 0
|
59
|
+
end
|
60
|
+
if options[:csv]
|
61
|
+
puts records_as_csv(json_response['contacts'], options)
|
62
|
+
return 0
|
63
|
+
end
|
64
|
+
contacts = json_response['contacts']
|
65
|
+
title = "Morpheus Monitoring Contacts"
|
66
|
+
subtitles = []
|
67
|
+
if params[:phrase]
|
68
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
69
|
+
end
|
70
|
+
print_h1 title, subtitles
|
71
|
+
if contacts.empty?
|
72
|
+
print cyan,"No contacts found.",reset,"\n"
|
73
|
+
else
|
74
|
+
print_contacts_table(contacts, options)
|
75
|
+
print_results_pagination(json_response, {:label => "contact", :n_label => "contacts"})
|
76
|
+
end
|
77
|
+
print reset,"\n"
|
78
|
+
rescue RestClient::Exception => e
|
79
|
+
print_rest_exception(e, options)
|
80
|
+
exit 1
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def get(args)
|
85
|
+
options = {}
|
86
|
+
optparse = OptionParser.new do|opts|
|
87
|
+
opts.banner = subcommand_usage("[id list]")
|
88
|
+
opts.on(nil,'--history', "Display History") do |val|
|
89
|
+
options[:show_history] = true
|
90
|
+
end
|
91
|
+
opts.on(nil,'--notifications', "Display Notifications") do |val|
|
92
|
+
options[:show_notifications] = true
|
93
|
+
end
|
94
|
+
build_common_options(opts, options, [:json, :csv, :fields, :dry_run, :remote])
|
95
|
+
end
|
96
|
+
optparse.parse!(args)
|
97
|
+
if args.count < 1
|
98
|
+
puts optparse
|
99
|
+
exit 1
|
100
|
+
end
|
101
|
+
connect(options)
|
102
|
+
id_list = parse_id_list(args)
|
103
|
+
return run_command_for_each_arg(id_list) do |arg|
|
104
|
+
_get(arg, options)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def _get(id, options)
|
109
|
+
|
110
|
+
begin
|
111
|
+
contact = find_contact_by_name_or_id(id)
|
112
|
+
if options[:dry_run]
|
113
|
+
print_dry_run @monitoring_interface.contacts.dry.get(contact['id'])
|
114
|
+
return
|
115
|
+
end
|
116
|
+
json_response = @monitoring_interface.contacts.get(contact['id'])
|
117
|
+
contact = json_response['contact']
|
118
|
+
|
119
|
+
if options[:json]
|
120
|
+
if options[:include_fields]
|
121
|
+
json_response = {"contact" => filter_data(json_response["contact"], options[:include_fields]) }
|
122
|
+
end
|
123
|
+
puts as_json(json_response, options)
|
124
|
+
return 0
|
125
|
+
elsif options[:csv]
|
126
|
+
puts records_as_csv([json_response['contact']], options)
|
127
|
+
return 0
|
128
|
+
end
|
129
|
+
|
130
|
+
print_h1 "Contact Details"
|
131
|
+
print cyan
|
132
|
+
description_cols = {
|
133
|
+
"ID" => 'id',
|
134
|
+
"Name" => 'name',
|
135
|
+
"Email" => 'emailAddress',
|
136
|
+
"Mobile" => 'smsAddress',
|
137
|
+
# "Slack Hook" => 'slackHook'
|
138
|
+
}
|
139
|
+
description_cols["Slack Hook"] = 'slackHook' if !contact['slackHook'].empty?
|
140
|
+
puts as_description_list(contact, description_cols)
|
141
|
+
|
142
|
+
## Notifications
|
143
|
+
# show notify events here...
|
144
|
+
|
145
|
+
print reset,"\n"
|
146
|
+
|
147
|
+
rescue RestClient::Exception => e
|
148
|
+
print_rest_exception(e, options)
|
149
|
+
exit 1
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def add(args)
|
154
|
+
options = {}
|
155
|
+
params = {}
|
156
|
+
optparse = OptionParser.new do|opts|
|
157
|
+
opts.banner = subcommand_usage("[id]")
|
158
|
+
opts.on("--name STRING", String, "Contact name") do |val|
|
159
|
+
params['name'] = val
|
160
|
+
end
|
161
|
+
opts.on("--email STRING", String, "Contact email address") do |val|
|
162
|
+
params['emailAddress'] = val == 'null' ? nil : val
|
163
|
+
end
|
164
|
+
opts.on("--mobile STRING", String, "Contact sms addresss") do |val|
|
165
|
+
params['smsAddress'] = val == 'null' ? nil : val
|
166
|
+
end
|
167
|
+
opts.on("--slackHook STRING", String, "Contact slack hook") do |val|
|
168
|
+
params['slackHook'] = val == 'null' ? nil : val
|
169
|
+
end
|
170
|
+
build_common_options(opts, options, [:json, :dry_run, :quiet])
|
171
|
+
end
|
172
|
+
optparse.parse!(args)
|
173
|
+
connect(options)
|
174
|
+
|
175
|
+
begin
|
176
|
+
|
177
|
+
if !params["name"]
|
178
|
+
print_red_alert "Name is required"
|
179
|
+
puts optparse
|
180
|
+
exit 1
|
181
|
+
end
|
182
|
+
|
183
|
+
payload = {
|
184
|
+
'contact' => {}
|
185
|
+
}
|
186
|
+
payload['contact'].merge!(params)
|
187
|
+
|
188
|
+
if options[:dry_run]
|
189
|
+
print_dry_run @monitoring_interface.contacts.dry.create(payload)
|
190
|
+
return
|
191
|
+
end
|
192
|
+
|
193
|
+
json_response = @monitoring_interface.contacts.create(payload)
|
194
|
+
contact = json_response['contact']
|
195
|
+
if options[:json]
|
196
|
+
puts as_json(json_response, options)
|
197
|
+
elsif !options[:quiet]
|
198
|
+
print_green_success "Created contact (#{contact['id']}) #{contact['name']}"
|
199
|
+
#_get(contact['id'], {})
|
200
|
+
end
|
201
|
+
|
202
|
+
rescue RestClient::Exception => e
|
203
|
+
print_rest_exception(e, options)
|
204
|
+
exit 1
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def update(args)
|
209
|
+
options = {}
|
210
|
+
params = {}
|
211
|
+
optparse = OptionParser.new do|opts|
|
212
|
+
opts.banner = subcommand_usage("[id]")
|
213
|
+
opts.on("--name STRING", String, "Contact name") do |val|
|
214
|
+
params['name'] = val
|
215
|
+
end
|
216
|
+
opts.on("--email STRING", String, "Contact email address") do |val|
|
217
|
+
params['emailAddress'] = val == 'null' ? nil : val
|
218
|
+
end
|
219
|
+
opts.on("--mobile STRING", String, "Contact sms addresss") do |val|
|
220
|
+
params['smsAddress'] = val == 'null' ? nil : val
|
221
|
+
end
|
222
|
+
opts.on("--slackHook STRING", String, "Contact slack hook") do |val|
|
223
|
+
params['slackHook'] = val == 'null' ? nil : val
|
224
|
+
end
|
225
|
+
build_common_options(opts, options, [:json, :dry_run, :quiet])
|
226
|
+
end
|
227
|
+
optparse.parse!(args)
|
228
|
+
if args.count < 1
|
229
|
+
puts optparse
|
230
|
+
exit 1
|
231
|
+
end
|
232
|
+
connect(options)
|
233
|
+
|
234
|
+
begin
|
235
|
+
contact = find_contact_by_name_or_id(args[0])
|
236
|
+
|
237
|
+
if params.empty?
|
238
|
+
print_red_alert "Specify atleast one option to update"
|
239
|
+
puts optparse
|
240
|
+
exit 1
|
241
|
+
end
|
242
|
+
|
243
|
+
payload = {
|
244
|
+
'contact' => {id: contact["id"]}
|
245
|
+
}
|
246
|
+
payload['contact'].merge!(params)
|
247
|
+
|
248
|
+
if options[:dry_run]
|
249
|
+
print_dry_run @monitoring_interface.contacts.dry.update(contact["id"], payload)
|
250
|
+
return
|
251
|
+
end
|
252
|
+
|
253
|
+
json_response = @monitoring_interface.contacts.update(contact["id"], payload)
|
254
|
+
if options[:json]
|
255
|
+
puts as_json(json_response, options)
|
256
|
+
elsif !options[:quiet]
|
257
|
+
print_green_success "Updated contact #{contact['id']}"
|
258
|
+
_get(contact['id'], {})
|
259
|
+
end
|
260
|
+
|
261
|
+
rescue RestClient::Exception => e
|
262
|
+
print_rest_exception(e, options)
|
263
|
+
exit 1
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
|
268
|
+
def remove(args)
|
269
|
+
options = {}
|
270
|
+
optparse = OptionParser.new do|opts|
|
271
|
+
opts.banner = subcommand_usage("[id list]")
|
272
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
273
|
+
end
|
274
|
+
optparse.parse!(args)
|
275
|
+
if args.count < 1
|
276
|
+
puts optparse
|
277
|
+
exit 1
|
278
|
+
end
|
279
|
+
connect(options)
|
280
|
+
id_list = parse_id_list(args)
|
281
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to delete contact #{id_list.size == 1 ? 'contact' : 'contacts'} #{anded_list(id_list)}?", options)
|
282
|
+
exit 1
|
283
|
+
end
|
284
|
+
return run_command_for_each_arg(id_list) do |arg|
|
285
|
+
_remove(arg, options)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def _remove(id, options)
|
290
|
+
|
291
|
+
begin
|
292
|
+
contact = find_contact_by_name_or_id(id)
|
293
|
+
if options[:dry_run]
|
294
|
+
print_dry_run @monitoring_interface.contacts.dry.destroy(contact['id'])
|
295
|
+
return
|
296
|
+
end
|
297
|
+
json_response = @monitoring_interface.contacts.destroy(contact['id'])
|
298
|
+
if options[:json]
|
299
|
+
puts as_json(json_response, options)
|
300
|
+
elsif !options[:quiet]
|
301
|
+
print_green_success json_response["msg"] || "Contact (#{contact['id']}) #{contact['name']} deleted"
|
302
|
+
end
|
303
|
+
rescue RestClient::Exception => e
|
304
|
+
print_rest_exception(e, options)
|
305
|
+
exit 1
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def reopen(args)
|
310
|
+
options = {}
|
311
|
+
optparse = OptionParser.new do|opts|
|
312
|
+
opts.banner = subcommand_usage("[id list]")
|
313
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
314
|
+
end
|
315
|
+
optparse.parse!(args)
|
316
|
+
if args.count < 1
|
317
|
+
puts optparse
|
318
|
+
exit 1
|
319
|
+
end
|
320
|
+
connect(options)
|
321
|
+
id_list = parse_id_list(args)
|
322
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to reopen #{id_list.size == 1 ? 'contact' : 'contacts'} #{anded_list(id_list)}?", options)
|
323
|
+
exit 1
|
324
|
+
end
|
325
|
+
return run_command_for_each_arg(id_list) do |arg|
|
326
|
+
_reopen(arg, options)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def _reopen(id, options)
|
331
|
+
|
332
|
+
begin
|
333
|
+
contact = find_contact_by_name_or_id(id)
|
334
|
+
already_open = contact['status'] == 'open'
|
335
|
+
if already_open
|
336
|
+
print bold,yellow,"contact #{contact['id']} is already open",reset,"\n"
|
337
|
+
return false
|
338
|
+
end
|
339
|
+
if options[:dry_run]
|
340
|
+
print_dry_run @monitoring_interface.contacts.dry.reopen(contact['id'])
|
341
|
+
return
|
342
|
+
end
|
343
|
+
json_response = @monitoring_interface.contacts.reopen(contact['id'])
|
344
|
+
if options[:json]
|
345
|
+
print JSON.pretty_generate(json_response)
|
346
|
+
print "\n"
|
347
|
+
elsif !options[:quiet]
|
348
|
+
print_green_success json_response["msg"] || "contact #{contact['id']} is now open"
|
349
|
+
# _get(contact['id'] {})
|
350
|
+
end
|
351
|
+
rescue RestClient::Exception => e
|
352
|
+
print_rest_exception(e, options)
|
353
|
+
exit 1
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
private
|
358
|
+
|
359
|
+
def print_contacts_table(contacts, opts={})
|
360
|
+
columns = [
|
361
|
+
{"ID" => "id" },
|
362
|
+
{"NAME" => "name" },
|
363
|
+
{"E-MAIL" => "emailAddress" },
|
364
|
+
{"MOBILE" => "smsAddress" },
|
365
|
+
]
|
366
|
+
if opts[:include_fields]
|
367
|
+
columns = opts[:include_fields]
|
368
|
+
end
|
369
|
+
print as_pretty_table(contacts, columns, opts)
|
370
|
+
end
|
371
|
+
|
372
|
+
|
373
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
require 'morpheus/cli/mixins/monitoring_helper'
|
3
|
+
|
4
|
+
class Morpheus::Cli::MonitoringGroupsCommand
|
5
|
+
include Morpheus::Cli::CliCommand
|
6
|
+
include Morpheus::Cli::MonitoringHelper
|
7
|
+
|
8
|
+
set_command_name :'check-groups'
|
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
|
13
|
+
|
14
|
+
def initialize()
|
15
|
+
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
16
|
+
end
|
17
|
+
|
18
|
+
def connect(opts)
|
19
|
+
@api_client = establish_remote_appliance_connection(opts)
|
20
|
+
@monitoring_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).monitoring
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle(args)
|
24
|
+
handle_subcommand(args)
|
25
|
+
end
|
26
|
+
|
27
|
+
# todo: API updates and subcommands
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,711 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
require 'morpheus/cli/mixins/monitoring_helper'
|
3
|
+
|
4
|
+
class Morpheus::Cli::MonitoringIncidentsCommand
|
5
|
+
include Morpheus::Cli::CliCommand
|
6
|
+
include Morpheus::Cli::MonitoringHelper
|
7
|
+
|
8
|
+
set_command_name :incidents # :'monitoring-incidents'
|
9
|
+
register_subcommands :list, :stats, :get, :history, :notifications, :update, :close, :reopen, :quarantine
|
10
|
+
set_default_subcommand :list
|
11
|
+
|
12
|
+
def initialize()
|
13
|
+
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
14
|
+
end
|
15
|
+
|
16
|
+
def connect(opts)
|
17
|
+
@api_client = establish_remote_appliance_connection(opts)
|
18
|
+
@monitoring_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).monitoring
|
19
|
+
end
|
20
|
+
|
21
|
+
def handle(args)
|
22
|
+
handle_subcommand(args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def list(args)
|
26
|
+
options = {}
|
27
|
+
params = {}
|
28
|
+
optparse = OptionParser.new do|opts|
|
29
|
+
opts.banner = subcommand_usage()
|
30
|
+
opts.on('--status LIST', Array, "Filter by status. open, closed") do |list|
|
31
|
+
params['status'] = list
|
32
|
+
end
|
33
|
+
opts.on('--severity LIST', Array, "Filter by severity. critical, warning, info") do |list|
|
34
|
+
params['severity'] = list
|
35
|
+
end
|
36
|
+
build_common_options(opts, options, [:list, :last_updated, :json, :csv, :fields, :json, :dry_run])
|
37
|
+
end
|
38
|
+
optparse.parse!(args)
|
39
|
+
connect(options)
|
40
|
+
begin
|
41
|
+
[:phrase, :offset, :max, :sort, :direction, :lastUpdated].each do |k|
|
42
|
+
params[k] = options[k] unless options[k].nil?
|
43
|
+
end
|
44
|
+
# JD: lastUpdated 500ing, incidents don't have that property ? =o Fix it!
|
45
|
+
|
46
|
+
if options[:dry_run]
|
47
|
+
print_dry_run @monitoring_interface.incidents.dry.list(params)
|
48
|
+
return
|
49
|
+
end
|
50
|
+
|
51
|
+
json_response = @monitoring_interface.incidents.list(params)
|
52
|
+
if options[:json]
|
53
|
+
if options[:include_fields]
|
54
|
+
json_response = {"incidents" => filter_data(json_response["incidents"], options[:include_fields]) }
|
55
|
+
end
|
56
|
+
puts as_json(json_response, options)
|
57
|
+
return 0
|
58
|
+
end
|
59
|
+
if options[:csv]
|
60
|
+
puts records_as_csv(json_response['incidents'], options)
|
61
|
+
return 0
|
62
|
+
end
|
63
|
+
incidents = json_response['incidents']
|
64
|
+
title = "Morpheus Incidents"
|
65
|
+
subtitles = []
|
66
|
+
# if group
|
67
|
+
# subtitles << "Group: #{group['name']}".strip
|
68
|
+
# end
|
69
|
+
# if cloud
|
70
|
+
# subtitles << "Cloud: #{cloud['name']}".strip
|
71
|
+
# end
|
72
|
+
if params[:phrase]
|
73
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
74
|
+
end
|
75
|
+
print_h1 title, subtitles
|
76
|
+
if incidents.empty?
|
77
|
+
print cyan,"No incidents found.",reset,"\n"
|
78
|
+
else
|
79
|
+
print_incidents_table(incidents, options)
|
80
|
+
print_results_pagination(json_response, {:label => "incident", :n_label => "incidents"})
|
81
|
+
end
|
82
|
+
print reset,"\n"
|
83
|
+
rescue RestClient::Exception => e
|
84
|
+
print_rest_exception(e, options)
|
85
|
+
exit 1
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# this show date range counts and current open incidents
|
90
|
+
# it should be perhaps called 'summary' or 'dashboard'
|
91
|
+
# it is not stats about a particular incident
|
92
|
+
def stats(args)
|
93
|
+
options = {}
|
94
|
+
optparse = OptionParser.new do|opts|
|
95
|
+
opts.banner = subcommand_usage()
|
96
|
+
#opts.on('-j','--json', "JSON Output") do
|
97
|
+
opts.on( '-m', '--max MAX', "Max open incidents to display. Default is 25" ) do |max|
|
98
|
+
if max.to_s == 'all'
|
99
|
+
options[:max] = 10000 # 'all'
|
100
|
+
else
|
101
|
+
options[:max] = max.to_i
|
102
|
+
end
|
103
|
+
end
|
104
|
+
opts.on( '-o', '--offset OFFSET', "Offset open incidents results for pagination." ) do |offset|
|
105
|
+
options[:offset] = offset.to_i.abs
|
106
|
+
end
|
107
|
+
build_common_options(opts, options, [:json, :fields, :json, :dry_run])
|
108
|
+
end
|
109
|
+
optparse.parse!(args)
|
110
|
+
connect(options)
|
111
|
+
begin
|
112
|
+
params = {}
|
113
|
+
[:phrase, :offset, :max, :sort, :direction, :lastUpdated].each do |k|
|
114
|
+
params[k] = options[k] unless options[k].nil?
|
115
|
+
end
|
116
|
+
if options[:dry_run]
|
117
|
+
print_dry_run @monitoring_interface.incidents.dry.stats(params)
|
118
|
+
return
|
119
|
+
end
|
120
|
+
json_response = @monitoring_interface.incidents.stats(params)
|
121
|
+
if options[:json]
|
122
|
+
if options[:include_fields]
|
123
|
+
json_response.merge!({"openIncidents" => filter_data(json_response["openIncidents"], options[:include_fields])})
|
124
|
+
end
|
125
|
+
puts as_json(json_response, options)
|
126
|
+
return 0
|
127
|
+
end
|
128
|
+
# if options[:csv]
|
129
|
+
# puts records_as_csv(json_response['openIncidents'], options)
|
130
|
+
# return 0
|
131
|
+
# end
|
132
|
+
open_incidents = json_response['openIncidents']
|
133
|
+
open_incidents_count = json_response['openIncidentCount']
|
134
|
+
stats = json_response['incidentStats']
|
135
|
+
|
136
|
+
print_h1 "Morpheus Incidents: Stats"
|
137
|
+
print cyan
|
138
|
+
|
139
|
+
# print_h2 "Counts"
|
140
|
+
# print_description_list({
|
141
|
+
# "Today" => 'today',
|
142
|
+
# "Week" => 'week',
|
143
|
+
# "Month" => 'month',
|
144
|
+
# }, stats)
|
145
|
+
|
146
|
+
if stats
|
147
|
+
print justify_string("Today: #{stats['today']}", 20)
|
148
|
+
print justify_string("Week: #{stats['week']}", 20)
|
149
|
+
print justify_string("Month: #{stats['month']}", 20)
|
150
|
+
print "\n"
|
151
|
+
else
|
152
|
+
puts "No stats"
|
153
|
+
end
|
154
|
+
|
155
|
+
if !open_incidents || open_incidents.size() == 0
|
156
|
+
print bold,green,"0 open incidents",reset,"\n"
|
157
|
+
else
|
158
|
+
if open_incidents.size() == 1
|
159
|
+
#print bold,yellow,"#{open_incidents.size()} open incident",reset,"\n"
|
160
|
+
print_h2 "#{open_incidents.size()} open incident"
|
161
|
+
else
|
162
|
+
#print bold,yellow,"#{open_incidents.size()} open incidents",reset,"\n"
|
163
|
+
print_h2 "#{open_incidents.size()} open incidents"
|
164
|
+
end
|
165
|
+
options[:max] ||= 20
|
166
|
+
|
167
|
+
print_incidents_table(open_incidents)
|
168
|
+
if open_incidents.size > 0
|
169
|
+
print_results_pagination(size: open_incidents.size, total: open_incidents_count, offset: options[:offset])
|
170
|
+
end
|
171
|
+
end
|
172
|
+
print reset,"\n"
|
173
|
+
rescue RestClient::Exception => e
|
174
|
+
print_rest_exception(e, options)
|
175
|
+
exit 1
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def get(args)
|
180
|
+
options = {}
|
181
|
+
optparse = OptionParser.new do|opts|
|
182
|
+
opts.banner = subcommand_usage("[id list]")
|
183
|
+
opts.on(nil,'--history', "Display Incident History") do |val|
|
184
|
+
options[:show_history] = true
|
185
|
+
end
|
186
|
+
opts.on(nil,'--notifications', "Display Incident Notifications") do |val|
|
187
|
+
options[:show_notifications] = true
|
188
|
+
end
|
189
|
+
build_common_options(opts, options, [:json, :csv, :fields, :dry_run, :remote])
|
190
|
+
end
|
191
|
+
optparse.parse!(args)
|
192
|
+
if args.count < 1
|
193
|
+
puts optparse
|
194
|
+
exit 1
|
195
|
+
end
|
196
|
+
connect(options)
|
197
|
+
id_list = parse_id_list(args)
|
198
|
+
return run_command_for_each_arg(id_list) do |arg|
|
199
|
+
_get(arg, options)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def _get(id, options)
|
204
|
+
|
205
|
+
begin
|
206
|
+
incident = find_incident_by_id(id)
|
207
|
+
if options[:dry_run]
|
208
|
+
print_dry_run @monitoring_interface.incidents.dry.get(incident['id'])
|
209
|
+
return
|
210
|
+
end
|
211
|
+
json_response = @monitoring_interface.incidents.get(incident['id'])
|
212
|
+
incident = json_response['incident']
|
213
|
+
|
214
|
+
if options[:json]
|
215
|
+
if options[:include_fields]
|
216
|
+
json_response = {"incident" => filter_data(json_response["incident"], options[:include_fields]) }
|
217
|
+
end
|
218
|
+
puts as_json(json_response, options)
|
219
|
+
return 0
|
220
|
+
elsif options[:csv]
|
221
|
+
puts records_as_csv([json_response['incident']], options)
|
222
|
+
return 0
|
223
|
+
end
|
224
|
+
|
225
|
+
print_h1 "Incident Details"
|
226
|
+
print cyan
|
227
|
+
description_cols = {
|
228
|
+
"ID" => 'id',
|
229
|
+
"Severity" => lambda {|it| format_severity(it['severity']) },
|
230
|
+
"Name" => lambda {|it| it['displayName'] || it['name'] || 'No Subject' },
|
231
|
+
"Start" => lambda {|it| format_local_dt(it['startDate']) },
|
232
|
+
"End" => lambda {|it| format_local_dt(it['endDate']) },
|
233
|
+
"Duration" => lambda {|it| format_duration(it['startDate'], it['endDate']) },
|
234
|
+
"Status" => lambda {|it| format_monitoring_issue_status(it) },
|
235
|
+
"Visibility" => 'visibility',
|
236
|
+
"Last Check" => lambda {|it| format_local_dt(it['lastCheckTime']) },
|
237
|
+
"Last Error" => lambda {|it| it['lastError'] },
|
238
|
+
"Comment" => 'comment',
|
239
|
+
"Resolution" => 'resolution'
|
240
|
+
}
|
241
|
+
# description_cols.delete("End") if incident['endDate'].nil?
|
242
|
+
description_cols.delete("Comment") if incident['comment'].empty?
|
243
|
+
description_cols.delete("Resolution") if incident['resolution'].empty?
|
244
|
+
# description_cols.delete("Last Check") if incident['lastCheckTime'].empty?
|
245
|
+
# description_cols.delete("Last Error") if incident['lastError'].empty?
|
246
|
+
print_description_list(description_cols, incident)
|
247
|
+
# puts as_vertical_table(incident, description_cols)
|
248
|
+
## Issues
|
249
|
+
|
250
|
+
issues = json_response["issues"]
|
251
|
+
if issues && !issues.empty?
|
252
|
+
print_h2 "Issues"
|
253
|
+
print_incident_history_table(issues, options)
|
254
|
+
else
|
255
|
+
print "\n"
|
256
|
+
puts "No checks involved in this incident"
|
257
|
+
end
|
258
|
+
|
259
|
+
## History (MonitorIncidentEvent)
|
260
|
+
if options[:show_history]
|
261
|
+
# history_items = json_response["history"]
|
262
|
+
# gotta go get it
|
263
|
+
history_json_response = @monitoring_interface.incidents.history(incident["id"], {})
|
264
|
+
history_items = history_json_response["history"] || history_json_response["events"] || history_json_response["issues"]
|
265
|
+
issues = history_items
|
266
|
+
if history_items && !history_items.empty?
|
267
|
+
print_h2 "History"
|
268
|
+
print_incident_history_table(history_items, options)
|
269
|
+
print_results_pagination(history_json_response, {:label => "event", :n_label => "events"})
|
270
|
+
else
|
271
|
+
print "\n"
|
272
|
+
puts "No history found for this incident"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
## Members (MonitorIncidentNotifyEvent)
|
277
|
+
if options[:show_notifications]
|
278
|
+
# history_items = json_response["history"]
|
279
|
+
# gotta go get it
|
280
|
+
notifications_json_response = @monitoring_interface.incidents.notifications(incident["id"], {max: 10})
|
281
|
+
notification_items = notifications_json_response["notifications"]
|
282
|
+
if notification_items && notification_items.empty?
|
283
|
+
print_h2 "Notifications"
|
284
|
+
print_incident_notifications_table(notification_items, options)
|
285
|
+
print_results_pagination(notifications_json_response, {:label => "notification", :n_label => "notifications"})
|
286
|
+
else
|
287
|
+
print "\n"
|
288
|
+
puts "Nobody has been notified about this incident."
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
print reset,"\n"
|
293
|
+
|
294
|
+
rescue RestClient::Exception => e
|
295
|
+
print_rest_exception(e, options)
|
296
|
+
exit 1
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def history(args)
|
301
|
+
options = {}
|
302
|
+
params = {}
|
303
|
+
optparse = OptionParser.new do|opts|
|
304
|
+
opts.banner = subcommand_usage("[id] [options]")
|
305
|
+
# opts.on('--status LIST', Array, "Filter by status. open, closed") do |list|
|
306
|
+
# params['status'] = list
|
307
|
+
# end
|
308
|
+
opts.on('--severity LIST', Array, "Filter by severity. critical, warning, info") do |list|
|
309
|
+
params['severity'] = list
|
310
|
+
end
|
311
|
+
build_common_options(opts, options, [:list, :last_updated, :json, :csv, :fields, :json, :dry_run])
|
312
|
+
end
|
313
|
+
optparse.parse!(args)
|
314
|
+
if args.count < 1
|
315
|
+
puts optparse
|
316
|
+
exit 1
|
317
|
+
end
|
318
|
+
connect(options)
|
319
|
+
begin
|
320
|
+
incident = find_incident_by_id(args[0])
|
321
|
+
# return false if incident.nil?
|
322
|
+
|
323
|
+
[:phrase, :offset, :max, :sort, :direction, :lastUpdated].each do |k|
|
324
|
+
params[k] = options[k] unless options[k].nil?
|
325
|
+
end
|
326
|
+
# JD: lastUpdated 500ing, incidents don't have that property ? =o Fix it!
|
327
|
+
|
328
|
+
if options[:dry_run]
|
329
|
+
print_dry_run @monitoring_interface.incidents.dry.history(incident['id'], params)
|
330
|
+
return
|
331
|
+
end
|
332
|
+
|
333
|
+
json_response = @monitoring_interface.incidents.history(incident['id'], params)
|
334
|
+
if options[:json]
|
335
|
+
if options[:include_fields]
|
336
|
+
json_response = {"history" => filter_data(json_response["history"], options[:include_fields]) }
|
337
|
+
end
|
338
|
+
puts as_json(json_response, options)
|
339
|
+
return 0
|
340
|
+
end
|
341
|
+
if options[:csv]
|
342
|
+
puts records_as_csv(json_response['history'], options)
|
343
|
+
return 0
|
344
|
+
end
|
345
|
+
history_items = json_response['history']
|
346
|
+
title = "Incident History: #{incident['id']}: #{incident['displayName'] || incident['name']}"
|
347
|
+
subtitles = []
|
348
|
+
if params[:phrase]
|
349
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
350
|
+
end
|
351
|
+
print_h1 title, subtitles
|
352
|
+
if history_items.empty?
|
353
|
+
print cyan,"No history found.",reset,"\n"
|
354
|
+
else
|
355
|
+
print_incident_history_table(history_items, options)
|
356
|
+
print_results_pagination(json_response, {:label => "event", :n_label => "events"})
|
357
|
+
end
|
358
|
+
print reset,"\n"
|
359
|
+
rescue RestClient::Exception => e
|
360
|
+
print_rest_exception(e, options)
|
361
|
+
exit 1
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
def notifications(args)
|
366
|
+
options = {}
|
367
|
+
optparse = OptionParser.new do|opts|
|
368
|
+
opts.banner = subcommand_usage("[id] [options]")
|
369
|
+
build_common_options(opts, options, [:list, :json, :csv, :fields, :json, :dry_run])
|
370
|
+
end
|
371
|
+
optparse.parse!(args)
|
372
|
+
if args.count < 1
|
373
|
+
puts optparse
|
374
|
+
exit 1
|
375
|
+
end
|
376
|
+
connect(options)
|
377
|
+
begin
|
378
|
+
incident = find_incident_by_id(args[0])
|
379
|
+
# return false if incident.nil?
|
380
|
+
params = {}
|
381
|
+
[:phrase, :offset, :max, :sort, :direction].each do |k|
|
382
|
+
params[k] = options[k] unless options[k].nil?
|
383
|
+
end
|
384
|
+
|
385
|
+
if options[:dry_run]
|
386
|
+
print_dry_run @monitoring_interface.incidents.dry.notifications(incident['id'], params)
|
387
|
+
return
|
388
|
+
end
|
389
|
+
|
390
|
+
json_response = @monitoring_interface.incidents.notifications(incident['id'], params)
|
391
|
+
if options[:json]
|
392
|
+
if options[:include_fields]
|
393
|
+
json_response = {"notifications" => filter_data(json_response["notifications"], options[:include_fields]) }
|
394
|
+
end
|
395
|
+
puts as_json(json_response, options)
|
396
|
+
return 0
|
397
|
+
end
|
398
|
+
if options[:csv]
|
399
|
+
puts records_as_csv(json_response['notifications'], options)
|
400
|
+
return 0
|
401
|
+
end
|
402
|
+
notification_items = json_response['notifications']
|
403
|
+
title = "Incident Notifications: #{incident['id']}: #{incident['displayName'] || incident['name']}"
|
404
|
+
subtitles = []
|
405
|
+
if params[:phrase]
|
406
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
407
|
+
end
|
408
|
+
print_h1 title, subtitles
|
409
|
+
if notification_items.empty?
|
410
|
+
print cyan,"No notifications found.",reset,"\n"
|
411
|
+
else
|
412
|
+
print_incident_history_table(notification_items, options)
|
413
|
+
print_results_pagination(json_response, {:label => "notification", :n_label => "notifications"})
|
414
|
+
end
|
415
|
+
print reset,"\n"
|
416
|
+
rescue RestClient::Exception => e
|
417
|
+
print_rest_exception(e, options)
|
418
|
+
exit 1
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
def update(args)
|
423
|
+
options = {}
|
424
|
+
params = {}
|
425
|
+
optparse = OptionParser.new do|opts|
|
426
|
+
opts.banner = subcommand_usage("[id]")
|
427
|
+
opts.on("-c", "--comment STRING", String, "Comment on this incident") do |val|
|
428
|
+
params['comment'] = val == 'null' ? nil : val
|
429
|
+
end
|
430
|
+
opts.on("--resolution STRING", String, "Description of the resolution to this incident") do |val|
|
431
|
+
params['resolution'] = val == 'null' ? nil : val
|
432
|
+
end
|
433
|
+
opts.on("--status STATUS", String, "Set status (open or closed)") do |val|
|
434
|
+
params['status'] = val
|
435
|
+
end
|
436
|
+
opts.on("--severity STATUS", String, "Set severity (critical, warning or info)") do |val|
|
437
|
+
params['severity'] = val
|
438
|
+
end
|
439
|
+
opts.on("--name STRING", String, "Set display name (subject)") do |val|
|
440
|
+
params['name'] = val == 'null' ? nil : val
|
441
|
+
end
|
442
|
+
opts.on("--startDate TIME", String, "Set start time") do |val|
|
443
|
+
begin
|
444
|
+
params['startDate'] = parse_time(val).utc.iso8601
|
445
|
+
rescue => e
|
446
|
+
raise OptionParser::InvalidArgument.new "Failed to parse --startDate '#{val}'. Error: #{e}"
|
447
|
+
end
|
448
|
+
end
|
449
|
+
opts.on("--endDate TIME", String, "Set end time") do |val|
|
450
|
+
begin
|
451
|
+
params['endDate'] = parse_time(val).utc.iso8601
|
452
|
+
rescue => e
|
453
|
+
raise OptionParser::InvalidArgument.new "Failed to parse --endDate '#{val}'. Error: #{e}"
|
454
|
+
end
|
455
|
+
end
|
456
|
+
opts.on("--inUptime BOOL", String, "Set 'In Availability'") do |val|
|
457
|
+
params['inUptime'] = ['true','on'].include?(val.to_s.strip)
|
458
|
+
end
|
459
|
+
build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
|
460
|
+
end
|
461
|
+
optparse.parse!(args)
|
462
|
+
if args.count < 1
|
463
|
+
puts optparse
|
464
|
+
exit 1
|
465
|
+
end
|
466
|
+
connect(options)
|
467
|
+
|
468
|
+
begin
|
469
|
+
incident = find_incident_by_id(args[0])
|
470
|
+
|
471
|
+
if params['status'] == 'closed'
|
472
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to close the incident '#{incident['id']}'?", options)
|
473
|
+
return false
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
if params.empty?
|
478
|
+
print_red_alert "Specify atleast one option to update"
|
479
|
+
puts optparse
|
480
|
+
exit 1
|
481
|
+
end
|
482
|
+
|
483
|
+
payload = {
|
484
|
+
'incident' => {id: incident["id"]}
|
485
|
+
}
|
486
|
+
payload['incident'].merge!(params)
|
487
|
+
|
488
|
+
if options[:dry_run]
|
489
|
+
print_dry_run @monitoring_interface.incidents.dry.update(incident["id"], payload)
|
490
|
+
return
|
491
|
+
end
|
492
|
+
|
493
|
+
json_response = @monitoring_interface.incidents.update(incident["id"], payload)
|
494
|
+
if options[:json]
|
495
|
+
puts as_json(json_response, options)
|
496
|
+
elsif !options[:quiet]
|
497
|
+
print_green_success "Updated incident #{incident['id']}"
|
498
|
+
_get(incident['id'], {})
|
499
|
+
end
|
500
|
+
|
501
|
+
rescue RestClient::Exception => e
|
502
|
+
print_rest_exception(e, options)
|
503
|
+
exit 1
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
|
508
|
+
def quarantine(args)
|
509
|
+
options = {}
|
510
|
+
params = {'enabled' => true}
|
511
|
+
optparse = OptionParser.new do|opts|
|
512
|
+
opts.banner = subcommand_usage("[id list]")
|
513
|
+
# this one is a bit weird.. it's a way to toggle incident.inUptime
|
514
|
+
# opts.on("--enabled BOOL", String, "Quarantine can be removed with --enabled false") do |val|
|
515
|
+
# params['enabled'] = ['on','true'].include?(val.to_s.downcase)
|
516
|
+
# end
|
517
|
+
opts.on("-d", "--disabled", "Disable Quarantine instead") do
|
518
|
+
params['enabled'] = false
|
519
|
+
end
|
520
|
+
build_common_options(opts, options, [:json, :dry_run, :quiet])
|
521
|
+
end
|
522
|
+
optparse.parse!(args)
|
523
|
+
if args.count < 1
|
524
|
+
puts optparse
|
525
|
+
exit 1
|
526
|
+
end
|
527
|
+
connect(options)
|
528
|
+
|
529
|
+
begin
|
530
|
+
incident = find_incident_by_id(args[0])
|
531
|
+
|
532
|
+
if params.empty?
|
533
|
+
print_red_alert "Specify atleast one option to update"
|
534
|
+
puts optparse
|
535
|
+
exit 1
|
536
|
+
end
|
537
|
+
|
538
|
+
# payload = {
|
539
|
+
# 'incident' => {id: incident["id"]}
|
540
|
+
# }
|
541
|
+
# payload['incident'].merge!(params)
|
542
|
+
payload = params
|
543
|
+
|
544
|
+
if options[:dry_run]
|
545
|
+
print_dry_run @monitoring_interface.incidents.dry.update(incident["id"], payload)
|
546
|
+
return
|
547
|
+
end
|
548
|
+
|
549
|
+
json_response = @monitoring_interface.incidents.update(incident["id"], payload)
|
550
|
+
if options[:json]
|
551
|
+
puts as_json(json_response, options)
|
552
|
+
elsif !options[:quiet]
|
553
|
+
print_green_success "Quarantined incident #{incident['id']}"
|
554
|
+
_get(incident['id'], {})
|
555
|
+
end
|
556
|
+
|
557
|
+
rescue RestClient::Exception => e
|
558
|
+
print_rest_exception(e, options)
|
559
|
+
exit 1
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
def close(args)
|
564
|
+
options = {}
|
565
|
+
optparse = OptionParser.new do|opts|
|
566
|
+
opts.banner = subcommand_usage("[id list]")
|
567
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
568
|
+
end
|
569
|
+
optparse.parse!(args)
|
570
|
+
if args.count < 1
|
571
|
+
puts optparse
|
572
|
+
exit 1
|
573
|
+
end
|
574
|
+
connect(options)
|
575
|
+
id_list = parse_id_list(args)
|
576
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to close #{id_list.size == 1 ? 'incident' : 'incidents'} #{anded_list(id_list)}?", options)
|
577
|
+
exit 1
|
578
|
+
end
|
579
|
+
return run_command_for_each_arg(id_list) do |arg|
|
580
|
+
_close(arg, options)
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
def _close(id, options)
|
585
|
+
|
586
|
+
begin
|
587
|
+
incident = find_incident_by_id(id)
|
588
|
+
already_closed = incident['status'] == 'closed'
|
589
|
+
if options[:dry_run]
|
590
|
+
print_dry_run @monitoring_interface.incidents.dry.close(incident['id'])
|
591
|
+
return
|
592
|
+
end
|
593
|
+
json_response = @monitoring_interface.incidents.close(incident['id'])
|
594
|
+
if options[:json]
|
595
|
+
print JSON.pretty_generate(json_response)
|
596
|
+
print "\n"
|
597
|
+
elsif !options[:quiet]
|
598
|
+
print_green_success json_response["msg"] || "Incident #{incident['id']} is now closed"
|
599
|
+
# _get(incident['id'] {})
|
600
|
+
end
|
601
|
+
rescue RestClient::Exception => e
|
602
|
+
print_rest_exception(e, options)
|
603
|
+
exit 1
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
def reopen(args)
|
608
|
+
options = {}
|
609
|
+
optparse = OptionParser.new do|opts|
|
610
|
+
opts.banner = subcommand_usage("[id list]")
|
611
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
612
|
+
end
|
613
|
+
optparse.parse!(args)
|
614
|
+
if args.count < 1
|
615
|
+
puts optparse
|
616
|
+
exit 1
|
617
|
+
end
|
618
|
+
connect(options)
|
619
|
+
id_list = parse_id_list(args)
|
620
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to reopen #{id_list.size == 1 ? 'incident' : 'incidents'} #{anded_list(id_list)}?", options)
|
621
|
+
exit 1
|
622
|
+
end
|
623
|
+
return run_command_for_each_arg(id_list) do |arg|
|
624
|
+
_reopen(arg, options)
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
def _reopen(id, options)
|
629
|
+
|
630
|
+
begin
|
631
|
+
incident = find_incident_by_id(id)
|
632
|
+
already_open = incident['status'] == 'open'
|
633
|
+
if already_open
|
634
|
+
print bold,yellow,"Incident #{incident['id']} is already open",reset,"\n"
|
635
|
+
return false
|
636
|
+
end
|
637
|
+
if options[:dry_run]
|
638
|
+
print_dry_run @monitoring_interface.incidents.dry.reopen(incident['id'])
|
639
|
+
return
|
640
|
+
end
|
641
|
+
json_response = @monitoring_interface.incidents.reopen(incident['id'])
|
642
|
+
if options[:json]
|
643
|
+
print JSON.pretty_generate(json_response)
|
644
|
+
print "\n"
|
645
|
+
elsif !options[:quiet]
|
646
|
+
print_green_success json_response["msg"] || "Incident #{incident['id']} is now open"
|
647
|
+
# _get(incident['id'] {})
|
648
|
+
end
|
649
|
+
rescue RestClient::Exception => e
|
650
|
+
print_rest_exception(e, options)
|
651
|
+
exit 1
|
652
|
+
end
|
653
|
+
end
|
654
|
+
|
655
|
+
private
|
656
|
+
|
657
|
+
def print_incidents_table(incidents, opts={})
|
658
|
+
columns = [
|
659
|
+
{"ID" => lambda {|incident| incident['id'] } },
|
660
|
+
{"SEVERITY" => lambda {|incident| format_severity(incident['severity']) } },
|
661
|
+
{"NAME" => lambda {|incident| incident['displayName'] || incident['name'] || 'No Subject' } },
|
662
|
+
{"TIME" => lambda {|incident| format_local_dt(incident['startDate']) } },
|
663
|
+
{"STATUS" => lambda {|incident| format_monitoring_incident_status(incident) } },
|
664
|
+
{"DURATION" => lambda {|incident| format_duration(incident['startDate'], incident['endDate']) } }
|
665
|
+
]
|
666
|
+
if opts[:include_fields]
|
667
|
+
columns = opts[:include_fields]
|
668
|
+
end
|
669
|
+
print as_pretty_table(incidents, columns, opts)
|
670
|
+
end
|
671
|
+
|
672
|
+
def print_incident_history_table(history_items, opts={})
|
673
|
+
columns = [
|
674
|
+
# {"ID" => lambda {|issue| issue['id'] } },
|
675
|
+
{"SEVERITY" => lambda {|issue| format_severity(issue['severity']) } },
|
676
|
+
{"AVAILABLE" => lambda {|issue| format_boolean issue['available'] } },
|
677
|
+
{"TYPE" => lambda {|issue| issue["attachmentType"] } },
|
678
|
+
{"NAME" => lambda {|issue| issue['name'] } },
|
679
|
+
{"DATE CREATED" => lambda {|issue| format_local_dt(issue['startDate']) } }
|
680
|
+
]
|
681
|
+
if opts[:include_fields]
|
682
|
+
columns = opts[:include_fields]
|
683
|
+
end
|
684
|
+
print as_pretty_table(history_items, columns, opts)
|
685
|
+
end
|
686
|
+
|
687
|
+
def print_incident_notifications_table(notifications, opts={})
|
688
|
+
columns = [
|
689
|
+
{"NAME" => lambda {|notification| notification['recipient'] ? notification['recipient']['name'] : '' } },
|
690
|
+
{"DELIVERY TYPE" => lambda {|notification| notification['addressTypes'].to_s } },
|
691
|
+
{"NOTIFIED ON" => lambda {|notification| format_local_dt(notification['dateCreated']) } },
|
692
|
+
# {"AVAILABLE" => lambda {|notification| format_boolean notification['available'] } },
|
693
|
+
# {"TYPE" => lambda {|notification| notification["attachmentType"] } },
|
694
|
+
# {"NAME" => lambda {|notification| notification['name'] } },
|
695
|
+
{"DATE CREATED" => lambda {|notification|
|
696
|
+
date_str = format_local_dt(notification['startDate']).to_s
|
697
|
+
if notification['pendingUtil']
|
698
|
+
"(pending) #{date_str}"
|
699
|
+
else
|
700
|
+
date_str
|
701
|
+
end
|
702
|
+
} }
|
703
|
+
]
|
704
|
+
#event['pendingUntil']
|
705
|
+
if opts[:include_fields]
|
706
|
+
columns = opts[:include_fields]
|
707
|
+
end
|
708
|
+
print as_pretty_table(notifications, columns, opts)
|
709
|
+
end
|
710
|
+
|
711
|
+
end
|