File Coverage

blib/lib/OpenStack/MetaAPI/API/Service.pm
Criterion Covered Total %
statement 52 52 100.0
branch 17 26 65.3
condition 3 6 50.0
subroutine 10 10 100.0
pod 0 6 0.0
total 82 100 82.0


line stmt bran cond sub pod time code
1             package OpenStack::MetaAPI::API::Service;
2              
3 5     5   2870 use strict;
  5         14  
  5         175  
4 5     5   30 use warnings;
  5         10  
  5         119  
5              
6 5     5   35 use Moo;
  5         9  
  5         25  
7 5     5   3824 use OpenStack::MetaAPI::API::Specs::Default ();
  5         17  
  5         4179  
8              
9             has 'auth' => (is => 'ro', required => 1);
10             has 'name' => (is => 'ro', required => 1);
11             has 'region' => (is => 'ro', required => 1);
12              
13             has 'interface' => (is => 'ro', default => 'public'); # admin internal or public
14              
15             has 'client' => (
16             is => 'ro',
17             lazy => 1,
18             default => sub {
19             my ($self) = @_;
20              
21             return $self->auth->service(
22             $self->name,
23             region => $self->region,
24             interface => $self->interface);
25             },
26             handles => [qw/endpoint get put post delete/]
27              
28             );
29              
30             has 'api' => (is => 'ro', required => 1)
31             ; # this is backreference to the mainapi so we can call other services
32              
33             has 'api_specs' => (is => 'ro', lazy => 1, default => \&BUILD_api_specs);
34              
35             ## FIXME: this needs a refactor...
36             # idea always strip the version from endpoint so we can add it to the uri later..
37             # this would make uri consistent... and improve root_uri
38             has 'version' => ('is' => 'ro', lazy => 1, default => \&BUILD_version);
39             has 'version_prefix' => ('is' => 'ro'); # added to very routes [optional]
40              
41             has 'methods' => (is => 'ro', default => sub { return {} });
42              
43             sub BUILD {
44 8     8 0 72 my ($self, $args) = @_;
45              
46 8         210 $self->api_specs->setup_api_methods_for_service($self);
47              
48 8         70 return;
49             }
50              
51             sub BUILD_version {
52 5     5 0 42 my ($self) = @_;
53              
54 5         94 my $url = $self->client->endpoint;
55 5 100       2192 if ($url =~ m{/(v[0-9\.]+)}) {
56 3         20 return $1;
57             }
58 2         10 return 'default';
59             }
60              
61             sub BUILD_api_specs { # load specs
62 8     8 0 73 my ($self) = @_;
63              
64 8         155 my $v = $self->version;
65 8         45 $v =~ s{\.}{_};
66 8         50 my $pkg =
67             'OpenStack::MetaAPI::API::Specs::' . ucfirst($self->name) . '::' . $v;
68              
69 8         562 my $load = eval qq{ require $pkg; 1 };
70 8 100       48 if ($load) {
71 6         26 return $pkg->new();
72             }
73              
74             # default void specs [ undefined ]
75             # we do not have to define all specs for now
76 2         21 return OpenStack::MetaAPI::API::Specs::Default->new();
77             }
78              
79             sub root_uri {
80 19     19 0 47 my ($self, $uri) = @_;
81              
82 19 50       48 return unless defined $uri;
83              
84 19 50       83 return $uri if $uri =~ m{^v}; # already contains a version
85              
86             # endpoint already contains a version
87 19 50 33     425 return if $self->endpoint && $self->endpoint =~ m{:[\d]/v}a;
88              
89             # append our prefix to the endpoint
90 19 100       1492 if ($self->version_prefix) {
91 8         28 my $base = $self->version_prefix;
92 8 50       44 $base .= '/' unless $uri =~ m{^/};
93 8         27 $base .= $uri;
94 8         57 return $base;
95             }
96              
97 11         33 return $uri;
98             }
99              
100             sub setup_method {
101 30     30 0 85 my ($self, $name, $sub) = @_;
102              
103 30 50       79 die unless ref $self;
104 30 50       68 die "missing name" unless $name;
105 30 50       69 die unless ref $sub eq 'CODE';
106              
107 30         84 my $methods = $self->methods();
108 30 50       74 die "Method '$name' already exists" if defined $methods->{$name};
109 30 50       228 die "Function '$name' already exists for " . ref($self)
110             if $self->can($name);
111              
112 30         66 $methods->{$name} = $sub;
113              
114 30         96 return 1;
115             }
116              
117             ### not sure how to overwrite 'can' method to let Moo/Class::XSAccessor see the methods
118             sub can_method {
119 39     39 0 90 my ($self, $method) = @_; # Not shift, using goto.
120              
121             #my $sub = UNIVERSAL::can($self, $method);
122 39         141 my $sub = $self->can($method);
123              
124 39 100 66     139 if (not defined $sub && ref $self) {
125 28         90 $sub = $self->methods()->{$method};
126             }
127              
128 39         100 return $sub; # May be undefined.
129             }
130              
131             1;
132              
133             __END__