You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ngcp-api-tools/bin/ngcp-credit-warning

277 lines
6.8 KiB

#!/usr/bin/perl
use strict;
use warnings;
use English;
use Getopt::Long;
use Pod::Usage;
use NGCP::API::Client;
use Readonly;
use XML::Simple;
use Template;
use Email::Sender::Simple qw();
use Email::Simple;
use Email::Simple::Creator;
use Email::Sender::Transport::Sendmail qw();
Readonly my @required => qw();
Readonly my $config_file => '/etc/ngcp-panel/provisioning.conf';
my $page_size = 10;
my $opts = {
verbose => 0,
};
my $config;
GetOptions($opts,
'help|h' => sub { usage() },
'verbose',
) or usage();
sub check_params {
my @missing;
foreach my $param (@required) {
push @missing, $param unless $opts->{$param};
}
usage(join(' ', @missing)) if scalar @missing;
return;
}
sub usage {
my $missing = shift;
pod2usage(
-exitval => $missing ? 1 : 0,
-verbose => 1,
-message => $missing ? "Missing parameters: $missing" : '',
);
return;
}
sub load_config {
$config = XML::Simple->new()->XMLin(
$config_file,
ForceArray => [ 'credit_warnings' ],
) or die "Cannot load config: $config_file: $ERRNO\n";
return;
}
sub send_email {
my ($cwarning, $contracts) = @_;
my $template = get_email_template() || return;
my $vars = {
domain => $cwarning->{domain},
threshold => $cwarning->{threshold},
adminmail => $config->{adminmail},
};
foreach my $data (@{$contracts}) {
$vars->{contracts} .= sprintf ('contract_id: %s cash_balance: %s', @{$data}{qw(id cash_balance)});
$vars->{contracts} .= ' external_id: '. $data->{external_id} if $data->{external_id};
$vars->{contracts} .= ' threshold: '. $data->{threshold} if $data->{threshold};
$vars->{contracts} .= "\n";
}
my $tt = Template->new();
foreach my $field (keys %{$template}) {
my $out;
$tt->process(\$template->{$field}, $vars, \$out);
$template->{$field} = $out if $out;
}
my $transport = Email::Sender::Transport::Sendmail->new;
my $email = Email::Simple->create(
header => [
To => ref $cwarning->{recipients} eq 'ARRAY'
? join(', ', @{$cwarning->{recipients}})
: $cwarning->{recipients},
From => $template->{from_email},
Subject => $template->{subject},
],
body => $template->{body},
);
Email::Sender::Simple->send($email, { transport => $transport })
or die sprintf "Cannot send credit warning notification to %s: $ERRNO\n",
$email->header('To');
return;
}
sub get_data {
my ($uri, $link, $process_code) = @_;
$process_code = sub { return 0 } if 'CODE' ne ref $process_code;
my $client = NGCP::API::Client->new(
verbose => $opts->{verbose},
page_rows => $page_size,
);
my @result = ();
while (my $res = $client->next_page($uri)) {
return [] unless check_api_error($res);
my $res_hash = $res->as_hash;
my $data = $res_hash->{_embedded}{'ngcp:' . $link};
if ('ARRAY' eq ref $data) {
unless ($process_code->($data)) {
push @result, @{$data};
}
} elsif ($data) {
unless ($process_code->([ $data ])) {
push @result, $data;
}
}
}
return \@result;
}
sub check_api_error {
my $res = shift;
if ($res->is_success) {
return 1;
} else {
die($res->result . "\n") if (
$res->is_client_error
or ($res->is_server_error and not scalar grep { $_ == $res->code; } qw(502 503 504))
);
return 0;
}
}
sub get_email_template {
my $templates_data = get_data('/api/emailtemplates/', 'emailtemplates');
foreach my $template (@{$templates_data}) {
next unless $template->{name} eq 'credit_warning_default_email';
return $template;
}
return;
}
sub main {
check_params();
load_config();
my $cwarnings = ref $config->{credit_warnings} eq 'ARRAY'
? $config->{credit_warnings}
: [ $config->{credit_warnings} ];
foreach my $cwarning (@{$cwarnings}) {
unless ($cwarning->{recipients}) {
die "No recipients defined for domain: $cwarning->{domain}\n";
}
unless ($cwarning->{domain}) {
die "Missing domain in a credit warning check\n";
}
my @contracts;
get_data(sprintf('/api/customerbalances/?no_count=true&domain=%s&prepaid=1',
$cwarning->{domain}),
'customerbalances',
sub {
my $balances = shift;
foreach my $balance (@{$balances}) {
my $ratio = $balance->{ratio} // 1.0;
my $threshold = $cwarning->{threshold} * $ratio;
next if $balance->{cash_balance} >= $threshold;
my $data = {
map { $_ => $balance->{$_} } qw(id cash_balance external_id)
};
$data->{threshold} = $threshold if $ratio < 1.0;
push @contracts, $data;
}
return 1;
}
);
if (@contracts) {
eval {
send_email($cwarning, \@contracts);
};
print $EVAL_ERROR if $EVAL_ERROR;
}
}
return 0;
}
exit main();
__END__
=head1 NAME
ngcp-credit-warning - checks for contract balances above credit warning thresholds
=head1 SYNOPSIS
B<ngcp-credit-warning> [I<options>...]
=head1 DESCRIPTION
B<This program> checks for contract balances above credit warning thresholds
and sends email notifications about the incidents.
=head1 OPTIONS
=over 8
=item B<--verbose>
Show additional debug information. Default false.
=item B<--help>
Print a brief help message.
=back
=head1 EXIT STATUS
=over
=item B<0>
Command completed successfully.
=item B<1>
Command failed with errors.
=back
=head1 SEE ALSO
NGCP::API::Client
=head1 BUGS AND LIMITATIONS
Please report problems you notice to the Sipwise
Development Team <support@sipwise.com>.
=head1 AUTHOR
Kirill Solomko <ksolomko@sipwise.com>
=head1 LICENSE
Copyright (C) 2016 Sipwise GmbH, Austria
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.