File Coverage

blib/lib/Docker/Registry/V2.pm
Criterion Covered Total %
statement 69 74 93.2
branch 8 14 57.1
condition n/a
subroutine 15 19 78.9
pod 0 7 0.0
total 92 114 80.7


line stmt bran cond sub pod time code
1             package Docker::Registry::Call::Repositories;
2 4     4   1986 use Moo;
  4         9  
  4         24  
3 4     4   1318 use Types::Standard qw/Int/;
  4         9  
  4         35  
4             has n => (is => 'ro', isa => Int);
5             has limit => (is => 'ro', isa => Int);
6              
7             package Docker::Registry::Result::Repositories;
8 4     4   2401 use Moo;
  4         9  
  4         15  
9 4     4   1389 use Types::Standard qw/ArrayRef Str/;
  4         8  
  4         32  
10             has repositories => (is => 'ro', isa => ArrayRef[Str]);
11              
12             package Docker::Registry::Call::RepositoryTags;
13 4     4   2677 use Moo;
  4         12  
  4         14  
14 4     4   1313 use Types::Standard qw/Int Str/;
  4         8  
  4         17  
15             has repository => (is => 'ro', isa => Str, required => 1);
16             has n => (is => 'ro', isa => Int);
17             has limit => (is => 'ro', isa => Int);
18              
19             package Docker::Registry::Result::RepositoryTags;
20 4     4   2703 use Moo;
  4         10  
  4         20  
21 4     4   1311 use Types::Standard qw/ArrayRef Str/;
  4         9  
  4         25  
22             has name => (is => 'ro', isa => Str, required => 1);
23             has tags => (is => 'ro', isa => ArrayRef[Str], required => 1);
24              
25             package Docker::Registry::V2;
26 4     4   2589 use Moo;
  4         9  
  4         15  
27 4     4   2476 use Docker::Registry::Types qw(DockerRegistryURI);
  4         21  
  4         44  
28 4     4   1417 use Types::Standard qw/Str ConsumerOf/;
  4         12  
  4         19  
29              
30             has url => (is => 'ro', coerce => 1, isa => DockerRegistryURI, required => 1);
31             has api_base => (is => 'ro', default => 'v2');
32              
33             has caller => (is => 'ro', isa => ConsumerOf['Docker::Registry::IO'], default => sub {
34             require Docker::Registry::IO::Simple;
35             Docker::Registry::IO::Simple->new;
36             });
37             has auth => (is => 'ro', isa => ConsumerOf['Docker::Registry::Auth'], lazy => 1, builder => 'build_auth' );
38              
39             sub build_auth {
40 0     0 0 0 require Docker::Registry::Auth::None;
41 0         0 Docker::Registry::Auth::None->new;
42             };
43              
44 4     4   5418 use JSON::MaybeXS qw//;
  4         22428  
  4         2384  
45             has _json => (is => 'ro', default => sub {
46             JSON::MaybeXS->new;
47             });
48             sub process_json_response {
49 10     10 0 32 my ($self, $response) = @_;
50 10 100       60 if ($response->status == 200) {
    50          
51 7         16 my $struct = eval {
52 7         105 $self->_json->decode($response->content);
53             };
54 7 50       28 if ($@) {
55 0         0 Docker::Registry::Exception->throw({ message => $@ });
56             }
57 7         77 return $struct;
58             } elsif ($response->status == 401) {
59 0         0 Docker::Registry::Exception::Unauthorized->throw({
60             message => $response->content,
61             status => $response->status,
62             });
63             } else {
64 3         71 Docker::Registry::Exception::HTTP->throw({
65             message => $response->content,
66             status => $response->status
67             });
68             }
69             }
70              
71             sub repositories {
72 6     6 0 14373 my $self = shift;
73             # Inputs n, last
74             #
75             # GET /v2/_catalog
76             #
77             # Header next
78             # {
79             # "repositories": [
80             # ,
81             # ...
82             # ]
83             # }
84 6         550 my $call_class = 'Docker::Registry::Call::Repositories';
85 6         146 my $call = $call_class->new({ @_ });
86 6         5981 my $params = { };
87 6 50       44 $params->{ n } = $call->n if (defined $call->n);
88 6 50       29 $params->{ limit } = $call->limit if (defined $call->limit);
89              
90 6         347 my $request = Docker::Registry::Request->new(
91             parameters => $params,
92             method => 'GET',
93             url => (join '/', $self->url, $self->api_base, '_catalog')
94             );
95 6         573 my $scope = 'registry:catalog:*';
96 6         189 $request = $self->auth->authorize($request, $scope);
97 6         53 my $response = $self->caller->send_request($request);
98 6         8391 my $result_class = 'Docker::Registry::Result::Repositories';
99 6         40 my $result = $result_class->new($self->process_json_response($response));
100 3         4864 return $result;
101             }
102              
103             sub repository_tags {
104 4     4 0 11597 my $self = shift;
105              
106             # n, last
107             #GET /v2/$repository/tags/list
108             #
109             #{"name":"$repository","tags":["2017.09","latest"]}
110 4         10 my $call_class = 'Docker::Registry::Call::RepositoryTags';
111 4         48 my $call = $call_class->new({ @_ });
112 4         10403 my $params = { };
113              
114 4 50       33 $params->{ n } = $call->n if (defined $call->n);
115 4 50       33 $params->{ limit } = $call->limit if (defined $call->limit);
116              
117 4         142 my $request = Docker::Registry::Request->new(
118             parameters => $params,
119             method => 'GET',
120             url => (join '/', $self->url, $self->api_base, $call->repository, 'tags/list')
121             );
122 4         424 my $scope = sprintf 'repository:%s:%s', $call->repository, 'pull';
123 4         94 $request = $self->auth->authorize($request, $scope);
124 4         42 my $response = $self->caller->send_request($request);
125 4         3387 my $result_class = 'Docker::Registry::Result::RepositoryTags';
126 4         24 my $result = $result_class->new($self->process_json_response($response));
127 4         8480 return $result;
128             }
129              
130             sub is_registry {
131 0     0 0   my $self = shift;
132             # GET /v2
133             # if (200 or 401) and (header.Docker-Distribution-API-Version eq 'registry/2.0')
134             }
135              
136             # Actionable failure conditions, covered in detail in their relevant sections,
137             # are reported as part of 4xx responses, in a json response body. One or more
138             # errors will be returned in the following format:
139             # {
140             # "errors:" [{
141             # "code": ,
142             # "message": ,
143             # "detail":
144             # },
145             # ...
146             # ]
147             # }
148              
149             # ECR: returns 401 error body as "Not Authorized"
150       0 0   sub process_error {
151            
152             }
153              
154       0 0   sub request {
155            
156             }
157             1;