Change-Id: I377cfec13a7f18dc6e1688cd3b57dbc4d11210ad (cherry picked from commit 8d18584276558e3fed70c1043850e42d102139f9)changes/42/4942/95
parent
69966040c6
commit
ad62a1a5a1
@ -0,0 +1,161 @@
|
||||
package NGCP::Panel::Controller::API::MetaConfigDefs;
|
||||
use NGCP::Panel::Utils::Generic qw(:all);
|
||||
use boolean qw(true);
|
||||
use Data::HAL qw();
|
||||
use Data::HAL::Link qw();
|
||||
use HTTP::Headers qw();
|
||||
use HTTP::Status qw(:constants);
|
||||
use MooseX::ClassAttribute qw(class_has);
|
||||
use NGCP::Panel::Utils::DateTime;
|
||||
use NGCP::Panel::Utils::Preferences;
|
||||
use Path::Tiny qw(path);
|
||||
use Safe::Isa qw($_isa);
|
||||
use JSON::Types qw();
|
||||
use Config::General;
|
||||
require Catalyst::ActionRole::ACL;
|
||||
require Catalyst::ActionRole::CheckTrailingSlash;
|
||||
require Catalyst::ActionRole::HTTPMethods;
|
||||
require Catalyst::ActionRole::RequireSSL;
|
||||
|
||||
sub allowed_methods{
|
||||
return [qw/GET OPTIONS HEAD/];
|
||||
}
|
||||
|
||||
use base qw/Catalyst::Controller NGCP::Panel::Role::API/;
|
||||
|
||||
sub resource_name{
|
||||
return 'metaconfigdefs';
|
||||
}
|
||||
sub dispatch_path{
|
||||
return '/api/metaconfigdefs/';
|
||||
}
|
||||
sub relation{
|
||||
return 'http://purl.org/sipwise/ngcp-api/#rel-metaconfigdefs';
|
||||
}
|
||||
|
||||
__PACKAGE__->config(
|
||||
action => {
|
||||
map { $_ => {
|
||||
ACLDetachTo => '/api/root/invalid_user',
|
||||
AllowedRole => [qw/admin reseller/],#left adminand reseller, as test can run as reseller too. Just don't return full config
|
||||
Args => 0,
|
||||
Does => [qw(ACL CheckTrailingSlash RequireSSL)],
|
||||
Method => $_,
|
||||
Path => __PACKAGE__->dispatch_path,
|
||||
} } @{ __PACKAGE__->allowed_methods }
|
||||
},
|
||||
action_roles => [qw(HTTPMethods)],
|
||||
);
|
||||
|
||||
sub auto :Private {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
$self->set_body($c);
|
||||
$self->log_request($c);
|
||||
}
|
||||
|
||||
sub GET :Allow {
|
||||
my ($self, $c) = @_;
|
||||
{
|
||||
my @links;
|
||||
push @links,
|
||||
Data::HAL::Link->new(
|
||||
relation => 'curies',
|
||||
href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
|
||||
name => 'ngcp',
|
||||
templated => true,
|
||||
),
|
||||
Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
|
||||
Data::HAL::Link->new(relation => 'self', href => sprintf('%s', $self->dispatch_path));
|
||||
|
||||
my $hal = Data::HAL->new(
|
||||
links => [@links],
|
||||
);
|
||||
|
||||
#my $resource = $c->config;
|
||||
my $catalyst_config = Config::General->new($c->config->{'Plugin::ConfigLoader'}->{file});
|
||||
my %config_internal = $catalyst_config->getall();
|
||||
my %config;
|
||||
|
||||
$config{file} = $c->config->{'Plugin::ConfigLoader'}->{file};
|
||||
$config{numbermanagement}->{auto_sync_cli} = $config_internal{numbermanagement}->{auto_sync_cli};
|
||||
$config{numbermanagement}->{auto_allow_cli} = $config_internal{numbermanagement}->{auto_allow_cli};
|
||||
$config{features} = $config_internal{features};
|
||||
|
||||
my $meta = {
|
||||
collections => {
|
||||
#name => {
|
||||
#module => '',
|
||||
#allowed_methods => [],
|
||||
#module_item =>''
|
||||
#allowed_methods_item => [],
|
||||
#query_params => [],
|
||||
#allowed_roles => [],
|
||||
#container_item_id => '',
|
||||
#unique_fields => [['table.field','table1.fields1']],
|
||||
#}
|
||||
},
|
||||
};
|
||||
(my($files,$modules,$collections)) = NGCP::Panel::Utils::API::get_collections('NGCP::Panel::Controller::API::MetaConfigDefs');
|
||||
|
||||
for ( my $i=0; $i < $#$collections; $i++)
|
||||
{
|
||||
my $collection = $collections->[$i];
|
||||
my $module = $modules->[$i];
|
||||
my $module_item = $module.'Item';
|
||||
my $roles = $module->can('config') ? $module->config->{action}->{OPTIONS}->{AllowedRole}:[];
|
||||
(!(ref $roles eq 'ARRAY')) and $roles = [$roles];
|
||||
$meta->{collections}->{$collection} = {
|
||||
module => $module,
|
||||
allowed_methods => $module->can('config') ? $module->config->{action} : {},
|
||||
query_params => $module->can('query_params') ? [map {$_->{param}} @{$module->query_params}] : [],
|
||||
allowed_roles => [$roles],
|
||||
module_item => $module_item->can('config') ? $module_item : '',
|
||||
allowed_methods_item => $module_item->can('config') ? $module_item->config->{action} : {},
|
||||
#container_item_id => '',
|
||||
#unique_fields => [['table.field','table1.fields1']],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
my $resource = { config => \%config, meta => $meta };
|
||||
$hal->resource($resource);
|
||||
|
||||
my $response = HTTP::Response->new(HTTP_OK, undef,
|
||||
HTTP::Headers->new($hal->http_headers(skip_links => 1)), $hal->as_json);
|
||||
$c->response->headers($response->headers);
|
||||
$c->response->body($response->content);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub HEAD :Allow {
|
||||
my ($self, $c) = @_;
|
||||
$c->forward(qw(GET));
|
||||
$c->response->body(q());
|
||||
return;
|
||||
}
|
||||
|
||||
sub OPTIONS :Allow {
|
||||
my ($self, $c) = @_;
|
||||
my $allowed_methods = $self->allowed_methods_filtered($c);
|
||||
$c->response->headers(HTTP::Headers->new(
|
||||
Allow => join(', ', @{ $allowed_methods }),
|
||||
Accept_Post => 'application/hal+json; profile=http://purl.org/sipwise/ngcp-api/#rel-'.$self->resource_name,
|
||||
));
|
||||
$c->response->content_type('application/json');
|
||||
$c->response->body(JSON::to_json({ methods => $allowed_methods })."\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sub end : Private {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
$self->log_response($c);
|
||||
}
|
||||
|
||||
no Moose;
|
||||
1;
|
||||
|
||||
# vim: set tabstop=4 expandtab:
|
@ -0,0 +1,68 @@
|
||||
package NGCP::Panel::Utils::API;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Find::Rule;
|
||||
|
||||
|
||||
sub get_collections {
|
||||
my @files = @{get_collections_files()};
|
||||
my(@collections, @packages, @modules);
|
||||
foreach my $mod(@files) {
|
||||
# extract file base from path (e.g. Foo from lib/something/Foo.pm)
|
||||
$mod =~ s/^.+\/([a-zA-Z0-9_]+)\.pm$/$1/;
|
||||
my $package = 'NGCP::Panel::Controller::API::'.$mod;
|
||||
my $rel = lc $mod;
|
||||
$mod = 'NGCP::Panel::Controller::API::'.$mod;
|
||||
push @modules, $mod;
|
||||
push @packages, $package;
|
||||
push @collections, $rel;
|
||||
}
|
||||
return \@files, \@packages, \@collections, \@modules;
|
||||
}
|
||||
sub get_collections_files {
|
||||
my($library,$libpath) = @_;
|
||||
if(!$libpath){
|
||||
# figure out base path of our api modules
|
||||
$library ||= "NGCP/Panel/Controller/API/Root.pm";
|
||||
$libpath = $INC{$library};
|
||||
$libpath =~ s/\/[^\/]+$/\//;
|
||||
}
|
||||
# find all modules not called Root.pm and *Item.pm
|
||||
# (which should then be just collections)
|
||||
my $rootrule = File::Find::Rule->new->name('Root.pm');
|
||||
my $itemrule = File::Find::Rule->new->name('*Item.pm');
|
||||
my $rule = File::Find::Rule->new
|
||||
->mindepth(1)
|
||||
->maxdepth(1)
|
||||
->name('*.pm')
|
||||
->not($rootrule)
|
||||
->not($itemrule);
|
||||
my @colls = $rule->in($libpath);
|
||||
|
||||
return \@colls;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
NGCP::Panel::Utils::API
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A helper to manipulate REST API related data
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Irina Peshinskaya
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
This library is free software. You can redistribute it and/or modify
|
||||
it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
# vim: set tabstop=4 expandtab:
|
@ -0,0 +1,26 @@
|
||||
package Parent;
|
||||
|
||||
our $VERSION = 1.23;
|
||||
|
||||
sub VERSION { $VERSION }
|
||||
|
||||
sub child_version { $_[0]->VERSION }
|
||||
|
||||
package Child;
|
||||
use base qw(Parent);
|
||||
|
||||
our $VERSION = 5.43;
|
||||
|
||||
sub VERSION { $VERSION }
|
||||
|
||||
sub new { bless {}, $_[0]; }
|
||||
|
||||
sub parent_version { $_[0]->SUPER::VERSION }
|
||||
|
||||
|
||||
print "Child version is ", Child->VERSION, "\n"; # 5.43
|
||||
my $child = Child->new;
|
||||
|
||||
print "Child version: ", $child->VERSION, "\n"; # 5.43
|
||||
print "Parent version: ", $child->parent_version, "\n"; # 1.23
|
||||
print "Child version: ", $child->child_version, "\n"; # 5.43
|
@ -0,0 +1,153 @@
|
||||
use strict;
|
||||
|
||||
use Test::Collection;
|
||||
use Test::FakeData;
|
||||
use Test::More;
|
||||
use Data::Dumper;
|
||||
use Getopt::Long;
|
||||
use File::Find::Rule;
|
||||
use File::Basename;
|
||||
use Clone qw/clone/;
|
||||
|
||||
my $opt = {
|
||||
'collections' => {},
|
||||
};
|
||||
my $opt_in = {};
|
||||
GetOptions($opt_in,
|
||||
"help|h|?" ,
|
||||
"collections:s" ,
|
||||
"ignore-existence" ,
|
||||
) or pod2usage(2);
|
||||
my @opt_keys = keys %$opt_in;
|
||||
@{$opt}{ map{my $k=$_;$k=~s/\-/_/;$k;} @opt_keys } = map {my $v = $opt_in->{$_}; $v={ map {$_=>1;} split(/[^[:alnum:]]+/,$v ) }; $v;} @opt_keys ;
|
||||
print Dumper $opt;
|
||||
pod2usage(1) if $opt->{help};
|
||||
pod2usage(1) unless( 1
|
||||
# defined $opt->{collections} && defined $opt->{etc}
|
||||
);
|
||||
|
||||
|
||||
my $test_machine = Test::Collection->new('name'=>'','ALLOW_EMPTY_COLLECTION' => 1);
|
||||
my $fake_data = Test::FakeData->new;
|
||||
$test_machine->clear_cache;
|
||||
my $remote_config = $test_machine->init_catalyst_config;
|
||||
print Dumper $remote_config ;
|
||||
my $data = $remote_config->{meta}->{'collections'};
|
||||
|
||||
|
||||
my %test_exclude = (
|
||||
'metaconfigdefs' => 1,
|
||||
'subscriberpreferencedefs' => 1,
|
||||
'customerpreferencedefs' => 1,
|
||||
'domainpreferencedefs' => 1,
|
||||
'peeringserverpreferencedefs' => 1,
|
||||
'profilepreferencedefs' => 1,
|
||||
'subscriberpreferences' => 1,
|
||||
'customerpreferences' => 1,
|
||||
'domainpreferences' => 1,
|
||||
'peeringserverpreferences' => 1,
|
||||
'profilepreferences' => 1,
|
||||
'pbxdevicepreferencedefs' => 1,
|
||||
'pbxdeviceprofilepreferencedefs' => 1,
|
||||
#defs and preferences are tested in context of preferences
|
||||
'pbxdevicefirmwares' => 1, #too hard, fails with timeout on get
|
||||
#falis with: not ok 163 - ccmapentries: check_get2put: check put successful (Unprocessable Entity: Validation failed. field='mappings', input='ARRAY(0x1a53f278)', errors='Mappings field is required')
|
||||
'ccmapentries' => 1,
|
||||
#fails with:
|
||||
# got: 'https://127.0.0.1:1443/api/customerzonecosts/?page=1&rows=5&start=2016-10-01T000000&end=2016-10-31T235959'
|
||||
# expected: 'https://127.0.0.1:1443/api/customerzonecosts/?page=1&rows=5'
|
||||
'customerzonecosts' => 1,
|
||||
#fails with: Unsupported media type 'application/json', accepting text/plain or text/xml only.)
|
||||
'pbxdeviceconfigs' => 1,
|
||||
#fails with: not ok 1131 - rtcapps: check_get2put: check put successful (Unprocessable Entity: Invalid field 'apps'. Must be an array.)
|
||||
'rtcapps' => 1,
|
||||
#fails with: not ok 1176 - rtcnetworks: check_get2put: check put successful (Unprocessable Entity: Invalid field 'networks'. Must be an array.)
|
||||
'rtcnetworks' => 1,
|
||||
);
|
||||
my %test_exists;
|
||||
{
|
||||
my $dir = dirname($0);
|
||||
my $rule = File::Find::Rule->new
|
||||
->mindepth(1)
|
||||
->maxdepth(1)
|
||||
->name('api-*.t');
|
||||
%test_exists = map {$_=~s/\Q$dir\/\E//;$_ => 1} $rule->in($dir);
|
||||
}
|
||||
|
||||
my $res = {
|
||||
'collections_no_get' => [],
|
||||
'collections_empty' => [],
|
||||
'collections_not_empty' => [],
|
||||
'strange_item_actions' => {},
|
||||
'no_module_item' => [],
|
||||
'tests_exists' => \%test_exists,
|
||||
'tests_exists_skipped' => [],
|
||||
'checked' => [],
|
||||
'tests_exclude' => \%test_exclude,
|
||||
'opt' => $opt
|
||||
};
|
||||
foreach my $collection ( sort grep{(! ( scalar keys $opt->{collections} ) ) || $opt->{collections}->{$_} } keys %{$data} ){
|
||||
if(!$opt->{collections}->{$collection}){
|
||||
if($test_exists{'api-'.$collection.'.t'} && !$opt->{ignore_existence}){
|
||||
push @{$res->{'tests_exists_skipped'}}, $collection;
|
||||
#we will not test the same twice
|
||||
next;
|
||||
}
|
||||
next if $test_exclude{$collection};
|
||||
}
|
||||
|
||||
#print Dumper $data->{$collection}->{allowed_methods_item};
|
||||
#print Dumper $collection;
|
||||
|
||||
my $item_allowed_actions = { allowed => {} };
|
||||
if($data->{$collection}->{module_item}){
|
||||
if(ref $data->{$collection}->{allowed_methods_item} eq 'HASH'){
|
||||
$item_allowed_actions = { allowed => { map { $_ => 1 } keys %{$data->{$collection}->{allowed_methods_item}} }};
|
||||
}else{
|
||||
$res->{'strange_item_actions'}->{$collection} = $data->{$collection}->{allowed_methods_item};
|
||||
}
|
||||
}else{
|
||||
push @{$res->{'no_module_item'}}, $collection;
|
||||
}
|
||||
push @{$res->{'checked'}}, $collection;
|
||||
$test_machine->name($collection);
|
||||
$test_machine->NO_ITEM_MODULE($data->{$collection}->{module_item} ? 0 : 1 );
|
||||
{
|
||||
$test_machine->methods({
|
||||
collection => { allowed => { map { $_ => 1 } keys %{$data->{$collection}->{allowed_methods}} }},
|
||||
item => $item_allowed_actions,
|
||||
});
|
||||
}
|
||||
|
||||
$test_machine->check_bundle();
|
||||
if($test_machine->{methods}->{collection}->{allowed}->{GET}){
|
||||
my $item = $test_machine->get_item_hal();
|
||||
#if($item->{content}->{total_count}){
|
||||
if(!$test_machine->IS_EMPTY_COLLECTION){
|
||||
push @{$res->{'collections_not_empty'}}, $collection;
|
||||
if($data->{$collection}->{allowed_methods}->{POST}){
|
||||
my $item_post = clone($item);
|
||||
delete $item_post->{content}->{id};
|
||||
$test_machine->DATA_ITEM_STORE($item_post->{content});
|
||||
$test_machine->form_data_item();
|
||||
#test_machine->check_create_correct( 1 );
|
||||
}
|
||||
if($test_machine->{methods}->{item}->{allowed}->{PUT}){
|
||||
$test_machine->check_get2put();
|
||||
}
|
||||
}else{
|
||||
push @{$res->{'collections_empty'}}, $collection;
|
||||
}
|
||||
}else{
|
||||
push @{$res->{'collections_no_get'}}, $collection;
|
||||
}
|
||||
}
|
||||
|
||||
$test_machine->clear_test_data_all();
|
||||
done_testing;
|
||||
|
||||
undef $fake_data;
|
||||
undef $test_machine;
|
||||
|
||||
print Dumper $res;
|
||||
# vim: set tabstop=4 expandtab:
|
Loading…
Reference in new issue