diff --git a/Build.PL b/Build.PL new file mode 100644 index 0000000..f98a747 --- /dev/null +++ b/Build.PL @@ -0,0 +1,16 @@ +use Module::Build qw(); +my $builder = Module::Build->new( + module_name => 'NGCP-API-Client', + license => 'gpl', + dist_author => 'Kirill Solomko ', + dist_version_from => 'lib/NGCP/API/Client.pm', + requires => { + 'Config::Tiny' => 0, + 'IO::Socket::SSL' => 0, + 'JSON' => 0, + 'LWP::UserAgent' => 0, + 'NGCP::Panel' => 0.01, + 'Readonly' => 0, + }, +); +$builder->create_build_script; diff --git a/Changes b/Changes new file mode 100644 index 0000000..81acecb --- /dev/null +++ b/Changes @@ -0,0 +1,4 @@ +Revision history for NGCP::API::Client + +Please check the package changelog for more info + diff --git a/README b/README new file mode 100644 index 0000000..f72b298 --- /dev/null +++ b/README @@ -0,0 +1,36 @@ +=head1 NAME + +NGCP::API::Client - Client interface for the REST API + +=head1 VERSION + +Check debian/changelog + +=head1 COMPATIBILITY + +The version is compatible with NGCP platforms version >= mr4.3.x + +=head1 INSTALLATION + +The module is a part of the debian package. + +=head1 DEPENDENCIES + +See distribution meta file. + +=head1 LICENCE + +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 . diff --git a/debian/ngcp-api-tools.install b/debian/ngcp-api-tools.install new file mode 100644 index 0000000..5a3e750 --- /dev/null +++ b/debian/ngcp-api-tools.install @@ -0,0 +1 @@ +usr/share/perl5/NGCP/API/Client.pm usr/share/perl5/NGCP/API/ diff --git a/lib/NGCP/API/Client.pm b/lib/NGCP/API/Client.pm new file mode 100644 index 0000000..3eb5cc9 --- /dev/null +++ b/lib/NGCP/API/Client.pm @@ -0,0 +1,230 @@ +package NGCP::API::Client; +use strict; +use warnings; +use English qw(-no_match_vars); +use Config::Tiny; +use JSON qw(to_json); +use IO::Socket::SSL; +use LWP::UserAgent; +use Readonly; + +Readonly my $cfg => Config::Tiny->read("/etc/default/ngcp-api") + or die "Cannot read /etc/default/ngcp-api: $ERRNO"; + +my %opts = (); + +sub new { + my $class = shift; + my $self = {}; + + $opts{host} = $cfg->{_}->{NGCP_API_IP}; + $opts{port} = $cfg->{_}->{NGCP_API_PORT}; + $opts{sslverify} = $cfg->{_}->{NGCP_API_SSLVERIFY} || 'yes'; + $opts{auth_user} = $cfg->{_}->{AUTH_SYSTEM_LOGIN}; + $opts{auth_pass} = $cfg->{_}->{AUTH_SYSTEM_PASSWORD}; + $opts{verbose} = 0; + + return bless $self, $class; +} + +sub request { + my ($self, $method, $uri, $data) = @_; + + my $ua = LWP::UserAgent->new(); + if ($opts{sslverify} eq 'no') { + $ua->ssl_opts( + verify_hostname => 0, + SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE, + ); + } + + my $urlbase = sprintf "%s:%s", @{opts}{qw(host port)}; + my $url = sprintf "https://%s%s", $urlbase, $uri =~ m#^/# ? $uri + : "/".$uri; + $ua->credentials($urlbase, 'api_admin_system', + @{opts}{qw(auth_user auth_pass)}); + + if($opts{verbose}) { + $ua->show_progress(1); + $ua->add_handler("request_send", sub { shift->dump; return }); + $ua->add_handler("response_done", sub { shift->dump; return }); + } + + my $req = HTTP::Request->new($method, $url); + + if ($method eq "PATCH") { + $req->header('Content-Type' => 'application/json-patch+json'); + } else { + $req->header('Content-Type' => 'application/json'); + } + $req->header('Prefer' => 'return=representation'); + $req->header('NGCP-UserAgent' => 'NGCP::API::Client'); + + $data and $req->content(to_json($data)); + + my $res = $ua->request($req); + + if($res->is_success) { + return NGCP::API::Client::Result->new($res); + } else { + die $res->as_string; + } + return; +} + +sub set_verbose { + my $self = shift; + + $opts{verbose} = shift || 0; + + return; +} + +package NGCP::API::Client::Result; +use warnings; +use strict; +use JSON qw(from_json); + +my $result; + +sub new { + my ($class, $res_obj) = @_; + $result = $res_obj; + return bless {}, $class; +} + +sub headers { + my $self = shift; + + return $result->headers; +} + +sub content { + my $self = shift; + + return $result->content; +} + +sub status_line { + my $self = shift; + + return $result->status_line; +} + +sub as_hash { + my $self = shift; + + return from_json($result->content, { utf8 => 1 }); +} + +1; + +__END__ + +=pod + +=head1 NAME + +NGCP::API::Client - Client interface for the REST API + +=head1 VERSION + +See the package changelog + +=head1 COMPATIBILITY + +The version is compatible with NGCP platforms version >= mr4.3.x + +=head1 SYNOPSIS + +=head2 + + my $client = new NGCP::API::Client; + + # GET (list) + + my $uri = '/api/customers/'; + my $res = $client->request("GET", $uri); + + # POST (create) + + my $uri = '/api/customers/'; + my $data = { contact_id => 4, + status => "test", + billing_profile_id => 4, + type => "sipaccount" }; + my $res = $client->request("POST", $uri, $data); + + # PUT (update) + + my $uri = '/api/customers/2'; + my $data = { contact_id => 4, + status => "test", + billing_profile_id => 4, + type => "sipaccount" }; + my $res = $client->request("POST", $uri, $data); + + # PATCH (update fields) + + my $uri = '/api/customers/2'; + my $data = [ { op => "remove", + path => "/add_vat" }, + { op => "replace", + path => "/contact_id", + value => 5 } ]; + my $res = $client->request("PATCH", $uri, $data); + + # DELETE (remove) + + my $uri = '/api/customers/2'; + my $res = $client->request("DELETE", $uri); + + # $res - response is a json content + +=head1 DESCRIPTION + +The client is for internal REST API usage primarily by internal scripts and modules + +=head2 new() + +Return: NGCP::API::Client object + +=head2 request($method, $uri) + +Send a REST API request provided by a method (GET,POST,PUT,PATCH,DELETE) + +Return: NGCP::API::Client::Result object + +=head2 set_verbose(0|1) + +Enable/disable tracing of the request/response. + +Return: undef + +=head2 NGCP::API::Client::Result->content() + +Return: result as json serialized data + +=head2 NGCP::API::Client::Result->as_hash() + +Return: result as a hash reference + +=head1 BUGS AND LIMITATIONS + +L + +=head1 AUTHOR + +Kirill Solomko + +=head1 LICENSE + +This software is Copyright (c) 2016 by Sipwise GmbH, Austria. + +All rights reserved. You may not copy, distribute +or modify without prior written permission from +Sipwise GmbH, Austria. + +=cut + +# vim: sw=4 ts=4 et