Add Sirportly notification plugin
This commit is contained in:
parent
97f3184476
commit
a688b5290f
|
@ -0,0 +1,368 @@
|
|||
#
|
||||
# Copyright 2020 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package notification::sirportly::mode::ticket;
|
||||
|
||||
use base qw(centreon::plugins::mode);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use centreon::plugins::http;
|
||||
use centreon::plugins::statefile;
|
||||
use JSON::XS;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments => {
|
||||
'hostname:s' => { name => 'hostname', default => 'api.sirportly.com' },
|
||||
'port:s' => { name => 'port', default => 443 },
|
||||
'proto:s' => { name => 'proto', default => 'https' },
|
||||
'api-token:s' => { name => 'api_token' },
|
||||
'api-secret:s' => { name => 'api_secret' },
|
||||
'cache' => { name => 'cache' },
|
||||
'contact-name:s' => { name => 'contact_name', default => 'Centreon Notifications' },
|
||||
'contact-type:s' => { name => 'contact_type', default => 'telephone' },
|
||||
'contact-data:s' => { name => 'contact_data', default => '-' },
|
||||
'brand:s' => { name => 'brand' },
|
||||
'department:s' => { name => 'department' },
|
||||
'submit-user:s' => { name => 'submit_user' },
|
||||
'close-user:s' => { name => 'close_user' },
|
||||
'submit-status:s' => { name => 'submit_status' },
|
||||
'close-status:s' => { name => 'close_status' },
|
||||
'priority-mapping:s' => { name => 'priority_mapping' },
|
||||
'priority:s' => { name => 'priority' },
|
||||
'item-id:s' => { name => 'item_id' },
|
||||
'subject:s' => { name => 'subject' },
|
||||
'message:s' => { name => 'message' },
|
||||
'timeout:s' => { name => 'timeout' },
|
||||
});
|
||||
|
||||
$self->{http} = centreon::plugins::http->new(%options);
|
||||
$self->{cache} = centreon::plugins::statefile->new(%options);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->SUPER::init(%options);
|
||||
if (!defined($self->{option_results}->{api_token})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --api-token option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{api_secret})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --api-secret option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{brand})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --brand option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{department})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --department option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{submit_status})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --submit-status option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{close_status})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --close-status option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{priority})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --priority option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{item_id})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --item-id option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{subject})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --subject option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{message})) {
|
||||
$self->{output}->add_option_msg(short_msg => "You need to set --message option");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
$self->{http}->set_options(%{$self->{option_results}});
|
||||
$self->{cache}->check_options(option_results => $self->{option_results});
|
||||
}
|
||||
|
||||
sub proceed {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
# Let's compute a priority mapping hash, with lc keys
|
||||
my %priority_mapping;
|
||||
if (defined($self->{option_results}->{priority_mapping})) {
|
||||
my $i = 0;
|
||||
%priority_mapping = map { $i++ % 2 ? $_ : lc } split /[:,]/, $self->{option_results}->{priority_mapping};
|
||||
}
|
||||
|
||||
# Let's compute a ticket tag to be able to find the opened ticket later on
|
||||
my $tag = $options{item_id};
|
||||
if ($options{priority} =~ /^(UP|DOWN|UNREACHABLE)$/i) {
|
||||
$tag = "centreon-hst:$tag";
|
||||
} else {
|
||||
$tag = "centreon-svc:$tag";
|
||||
}
|
||||
|
||||
# Is there an existing Sirportly ticket for this item ?
|
||||
my $post_param = [
|
||||
"spql=SELECT tickets.reference,statuses.name FROM tickets WHERE ticket_tags.tag=\"$tag\" AND statuses.name!=\"$self->{option_results}->{close_status}\" ORDER BY tickets.submitted_at DESC LIMIT 1",
|
||||
];
|
||||
my $response = $self->{http}->request(method => 'POST', url_path =>'/api/v2/tickets/spql', post_param => $post_param, warning_status => '', unknown_status => '', critical_status => '');
|
||||
my $ticket_info;
|
||||
eval {
|
||||
$ticket_info = JSON::XS->new->decode($response)->{results}[0];
|
||||
};
|
||||
|
||||
# Close the ticket
|
||||
if ($options{priority} =~ /^(UP|OK)$/i) {
|
||||
if (defined($ticket_info)) {
|
||||
$post_param = [
|
||||
"ticket=$ticket_info->[0]",
|
||||
"contact=$self->{option_results}->{contact_name}",
|
||||
"message=$options{message}",
|
||||
];
|
||||
$self->{http}->request(method => 'POST', url_path =>'/api/v2/tickets/post_update', post_param => $post_param, warning_status => '', unknown_status => '', critical_status => '');
|
||||
if ($ticket_info->[1] eq $self->{option_results}->{submit_status}) {
|
||||
$post_param = [
|
||||
"ticket=$ticket_info->[0]",
|
||||
"user=" . (defined($self->{option_results}->{close_user}) ? $self->{option_results}->{close_user} : ""),
|
||||
"status=$self->{option_results}->{close_status}",
|
||||
];
|
||||
my $decoded = $self->{http}->request(method => 'POST', url_path =>'/api/v2/tickets/update', post_param => $post_param);
|
||||
eval {
|
||||
$decoded = JSON::XS->new->decode($response);
|
||||
};
|
||||
if ($@) {
|
||||
$ticket_info->[0] = "failed";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Update an existing ticket
|
||||
elsif (defined($ticket_info)) {
|
||||
$post_param = [
|
||||
"ticket=$ticket_info->[0]",
|
||||
"contact=$self->{option_results}->{contact_name}",
|
||||
"message=$options{message}",
|
||||
];
|
||||
$self->{http}->request(method => 'POST', url_path =>'/api/v2/tickets/post_update', post_param => $post_param, warning_status => '', unknown_status => '', critical_status => '');
|
||||
$post_param = [
|
||||
"ticket=$ticket_info->[0]",
|
||||
"priority=" . (defined($priority_mapping{lc($options{priority})}) ? $priority_mapping{lc($options{priority})} : $options{priority}),
|
||||
];
|
||||
my $decoded = $self->{http}->request(method => 'POST', url_path =>'/api/v2/tickets/update', post_param => $post_param);
|
||||
eval {
|
||||
$decoded = JSON::XS->new->decode($response);
|
||||
};
|
||||
if ($@) {
|
||||
$ticket_info->[0] = "failed";
|
||||
}
|
||||
}
|
||||
|
||||
# Open a new ticket
|
||||
else {
|
||||
$post_param = [
|
||||
"contact_name=$self->{option_results}->{contact_name}",
|
||||
"contact_method_type=$self->{option_results}->{contact_type}",
|
||||
"contact_method_data=$self->{option_results}->{contact_data}",
|
||||
"brand=$self->{option_results}->{brand}",
|
||||
"department=$self->{option_results}->{department}",
|
||||
"user=" . (defined($self->{option_results}->{submit_user}) ? $self->{option_results}->{submit_user} : ""),
|
||||
"status=$self->{option_results}->{submit_status}",
|
||||
"priority=" . (defined($priority_mapping{lc($options{priority})}) ? $priority_mapping{lc($options{priority})} : $options{priority}),
|
||||
"tag_list=$tag",
|
||||
"subject=$options{subject}",
|
||||
"message=$options{message}",
|
||||
];
|
||||
my $response = $self->{http}->request(method => 'POST', url_path =>'/api/v2/tickets/submit', post_param => $post_param, warning_status => '', unknown_status => '', critical_status => '');
|
||||
my $decoded;
|
||||
eval {
|
||||
$decoded = JSON::XS->new->decode($response);
|
||||
};
|
||||
if ($@ || !defined($decoded->{reference})) {
|
||||
$ticket_info->[0] = "failed";
|
||||
} else {
|
||||
$ticket_info->[0] = $decoded->{reference};
|
||||
}
|
||||
}
|
||||
|
||||
# Return proceeded ticket
|
||||
return $ticket_info->[0];
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
# Authentication headers
|
||||
$self->{http}->add_header(key => 'X-Auth-Token', value => $self->{option_results}->{api_token});
|
||||
$self->{http}->add_header(key => 'X-Auth-Secret', value => $self->{option_results}->{api_secret});
|
||||
|
||||
# Load cache
|
||||
$self->{cache}->read(statefile => 'sirportly_api_' . $self->{option_results}->{api_token});
|
||||
my $cache;
|
||||
if (defined($self->{option_results}->{cache})) {
|
||||
$cache = $self->{cache}->get(name => 'cache');
|
||||
} else {
|
||||
$cache = {};
|
||||
}
|
||||
|
||||
# Add current item to cache
|
||||
my $cache_index = time();
|
||||
$cache->{$cache_index}->{item_id} = $self->{option_results}->{item_id};
|
||||
$cache->{$cache_index}->{priority} = $self->{option_results}->{priority};
|
||||
$cache->{$cache_index}->{subject} = $self->{option_results}->{subject};
|
||||
$cache->{$cache_index}->{message} = $self->{option_results}->{message};
|
||||
$self->{cache}->write(data => {cache => $cache});
|
||||
|
||||
# Proceed cached notifications
|
||||
my $cache_size = keys %{$cache};
|
||||
my $cache_done = 0;
|
||||
foreach $cache_index (sort keys %{$cache}) {
|
||||
my $ticket_reference = $self->proceed(
|
||||
priority => $cache->{$cache_index}->{priority},
|
||||
item_id => $cache->{$cache_index}->{item_id},
|
||||
subject => $cache->{$cache_index}->{subject},
|
||||
message => $cache->{$cache_index}->{message},
|
||||
);
|
||||
if (!defined($ticket_reference) || $ticket_reference ne "failed") {
|
||||
delete($cache->{$cache_index});
|
||||
$self->{cache}->write(data => {cache => $cache});
|
||||
$cache_done++;
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# Exit
|
||||
$self->{output}->output_add(severity => ($cache_size == $cache_done) ? 'OK' : 'CRITICAL',
|
||||
short_msg => "Proceeded " . $cache_done . "/" . $cache_size . " notifications");
|
||||
$self->{output}->display(force_ignore_perfdata => 1);
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Open tickets via Sirportly API (https://sirportly.com/docs/api-specification/)
|
||||
|
||||
=over 6
|
||||
|
||||
=item B<--hostname>
|
||||
|
||||
Hostname of the OVH SMS API (default: 'api.sirportly.com').
|
||||
|
||||
=item B<--port>
|
||||
|
||||
Port used by API (default: '443').
|
||||
|
||||
=item B<--proto>
|
||||
|
||||
Specify https if needed (Default: 'https').
|
||||
|
||||
=item B<--api-token>
|
||||
|
||||
Specify the API authentication token.
|
||||
|
||||
=item B<--api-secret>
|
||||
|
||||
Specify the API authentication secret.
|
||||
|
||||
=item B<--cache>
|
||||
|
||||
Cache notifications not correctly delivered, to retry at next run.
|
||||
|
||||
=item B<--contact-name>
|
||||
|
||||
Specify the contact name for this ticket (default: 'Centreon Notifications').
|
||||
|
||||
=item B<--contact-type>
|
||||
|
||||
Specify the contact type (email or telephone) of the contact (default: 'telephone').
|
||||
|
||||
=item B<--contact-data>
|
||||
|
||||
Specify the email address or telephone number of the contact (default: '-').
|
||||
|
||||
=item B<--brand>
|
||||
|
||||
Specify the brand for this ticket.
|
||||
|
||||
=item B<--department>
|
||||
|
||||
Specify the department for this ticket.
|
||||
|
||||
=item B<--submit-user>
|
||||
|
||||
Specify the user to assign the ticket to when submitting the ticket.
|
||||
|
||||
=item B<--close-user>
|
||||
|
||||
Specify the user to assign the ticket to when closing the ticket.
|
||||
|
||||
=item B<--submit-status>
|
||||
|
||||
Specify the Sirportly status to be used when submitting the ticket.
|
||||
|
||||
=item B<--close-status>
|
||||
|
||||
Specify the Sirportly status to be used when closing the ticket.
|
||||
|
||||
=item B<--priority-mapping>
|
||||
|
||||
Map the Centreon priorities to Sirportly ones, comma separated (syntax: (down|unreachable|warning|critical|unknown):priority).
|
||||
|
||||
=item B<--priority>
|
||||
|
||||
Specify the priority for this ticket.
|
||||
|
||||
=item B<--item-id>
|
||||
|
||||
Specify the host or service ID for this ticket.
|
||||
|
||||
=item B<--subject>
|
||||
|
||||
Specify the subject for this ticket.
|
||||
|
||||
=item B<--message>
|
||||
|
||||
Specify the message for this ticket.
|
||||
|
||||
=item B<--timeout>
|
||||
|
||||
Threshold for HTTP timeout
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,48 @@
|
|||
#
|
||||
# Copyright 2020 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package notification::sirportly::plugin;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base qw(centreon::plugins::script_simple);
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
%{$self->{modes}} = (
|
||||
'ticket' => 'notification::sirportly::mode::ticket',
|
||||
);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 PLUGIN DESCRIPTION
|
||||
|
||||
Open tickets via Sirportly API.
|
||||
|
||||
=cut
|
Loading…
Reference in New Issue