#!/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 $opts = { verbose => 0, }; my $config; GetOptions( $opts, "help|h" => \&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 $msg = shift; pod2usage(-exitval => $msg ? 1 : 0, -verbose => 99, -sections => [ qw(NAME OPTIONS USAGE) ], -message => $msg ? $msg =~ /not found/i ? $msg : "Missing parameters: $msg" : '', ); return; } sub load_config { $config = XML::Simple->new()->XMLin($config_file, ForceArray => 0) or die "Cannot load config: $config_file: $ERRNO"; 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 <new(); map { my $out; $tt->process(\$template->{$_}, $vars, \$out); $out and $template->{$_} = $out; } keys %{$template}; 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", $email->header('To'); return; } sub get_data { my ($uri, $link) = @_; my $client = new NGCP::API::Client; $client->set_verbose($opts->{verbose}); my $res = $client->request("GET", $uri); die $res->result unless $res->is_success; my $res_hash = $res->as_hash; return [] unless $res_hash->{total_count} && $res_hash->{total_count} > 0; my $data = $res_hash->{_embedded}{'ngcp:'.$link}; return ref $data eq 'ARRAY' ? $data : [ $data ]; } 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}"; } unless ($cwarning->{domain}) { die "Missing domain in a credit warning check"; } my @contracts; my $balances = get_data(sprintf('/api/customerbalances/?domain=%s', $cwarning->{domain}), 'customerbalances'); foreach my $balance (@{$balances}) { next if $balance->{cash_balance} >= $cwarning->{threshold}; push @contracts, { map { $_ => $balance->{$_} } qw(id cash_balance) }; } if (@contracts) { send_email($cwarning, \@contracts); } } return; } main(); exit 0; __END__ =head1 NAME ngcp-credit-warning - checks for contract balances above credit warning thresholds =head1 OPTIONS =over 8 =item B<-help> Print a brief help message. =item B<-verbose> Show additional debug information. Default false. =back =head1 USAGE ngcp-credit-warning [options] =head1 DESCRIPTION B checks for contract balances above credit warning thresholds and sends email notifications about the incidents =head1 REQUIRED ARGUMENTS None =head1 EXIT STATUS Exit code 0 means everything is ok otherwise 1. =head1 CONFIGURATION =head1 DIAGNOSTICS =head1 SEE ALSO NGCP::API::Client =head1 DEPENDENCIES ngcp-credit-warning relies on a bunch of Perl modules, all of them specified as dependencies through the Debian package. =head1 INCOMPATIBILITIES No known at this time. =head1 BUGS AND LIMITATIONS Please report problems you notice to the Sipwise Development Team . =head1 AUTHOR Kirill Solomko =head1 LICENSE AND COPYRIGHT 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 . =cut