File Coverage

blib/lib/App/Docker/Client.pm
Criterion Covered Total %
statement 54 107 50.4
branch 10 36 27.7
condition 7 14 50.0
subroutine 17 27 62.9
pod 15 15 100.0
total 103 199 51.7


line stmt bran cond sub pod time code
1             package App::Docker::Client;
2              
3             =head1 NAME
4              
5             App::Docker::Client - Simple and plain Docker client!
6              
7             =head1 VERSION
8              
9             Version 0.010200
10              
11             =cut
12              
13             our $VERSION = '0.010200';
14              
15 3     3   43768 use 5.16.0;
  3         9  
16 3     3   13 use strict;
  3         5  
  3         52  
17 3     3   9 use warnings;
  3         6  
  3         68  
18 3     3   1921 use LWP::UserAgent;
  3         97527  
  3         84  
19 3     3   1844 use JSON;
  3         24169  
  3         12  
20 3     3   1752 use LWP::Protocol::http::SocketUnixAlt;
  3         104358  
  3         2361  
21              
22             =head2 new
23              
24             Constructor
25              
26             =cut
27              
28             sub new {
29 2     2 1 151714 my $class = shift;
30 2         6 my $self = {@_};
31 2         11 $self->{_scheme_postfixes} = { file => ':', http => '://', https => '://', };
32 2         27 $self->{_valid_codes} = { 200 => 1, 201 => 1, 204 => 1 };
33 2         4 bless $self, $class;
34 2         4 return $self;
35             }
36              
37             =head1 SUBROUTINES/METHODS
38              
39             =head2 with_valid_code
40              
41             =cut
42              
43             sub with_valid_code {
44 0     0 1 0 my ( $self, $code ) = @_;
45 0 0       0 return if $code !~ m/^(\d{3})$/;
46 0         0 $self->{_valid_codes}->{$code} = 1;
47 0         0 return $self;
48             }
49              
50             =head2 without_valid_code
51              
52             =cut
53              
54             sub without_valid_code {
55 0     0 1 0 my ( $self, $code ) = @_;
56 0 0       0 return if $code !~ m/^(\d{3})$/;
57 0         0 $self->{_valid_codes}->{$code} = 0;
58 0         0 return $self;
59             }
60              
61             =head2 show_progress
62              
63             =cut
64              
65             sub show_progress {
66 0     0 1 0 my ( $self, $show_progress ) = @_;
67 0 0       0 $self->{show_progress} = $show_progress ? $show_progress == 0 ? () : 1 : 1;
    0          
68 0         0 return $self;
69             }
70              
71             =head2 authority
72              
73             Getter/Setter for internal hash key authority.
74              
75             =cut
76              
77             sub authority {
78 4 100 100 4 1 27 return $_[0]->{authority} || '/var/run/docker.sock' unless $_[1];
79 1   50     4 $_[0]->{authority} = $_[1] || '/var/run/docker.sock';
80 1         3 return $_[0]->{authority};
81             }
82              
83             =head2 scheme
84              
85             Getter/Setter for internal hash key scheme.
86              
87             =cut
88              
89             sub scheme {
90 5 100 100 5 1 299 return $_[0]->{scheme} || 'http' unless $_[1];
91 1   50     3 $_[0]->{scheme} = $_[1] || 'http';
92 1         3 return $_[0]->{scheme};
93             }
94              
95             =head2 ssl_opts
96              
97             Getter/Setter for internal hash key ssl_opts.
98              
99             =cut
100              
101             sub ssl_opts {
102 0 0   0 1 0 return $_[0]->{ssl_opts} unless $_[1];
103 0         0 $_[0]->{ssl_opts} = $_[1];
104 0         0 return $_[0]->{ssl_opts};
105             }
106              
107             =head2 json
108              
109             Getter/Setter for internal hash key json.
110              
111             =cut
112              
113             sub json {
114 3 50 33 3 1 844 return $_[0]->{json} || JSON->new->utf8() unless $_[1];
115 0   0     0 $_[0]->{json} = $_[1] || JSON->new->utf8();
116 0         0 return $_[0]->{json};
117             }
118              
119             =head2 user_agent
120              
121             Getter/Setter for internal hash key UserAgent.
122              
123             =cut
124              
125             sub user_agent {
126 2     2 1 783 my ( $self, $user_agent ) = @_;
127 2 50       6 if ($user_agent) {
128 0         0 $self->{UserAgent} = $user_agent;
129 0         0 return $self->{UserAgent};
130             }
131 2 50       13 return $self->{UserAgent} if $self->{UserAgent};
132              
133 0 0       0 if ( -S $self->authority() ) {
134 0         0 LWP::Protocol::implementor( http => 'LWP::Protocol::http::SocketUnixAlt' );
135             }
136             $self->{UserAgent} = LWP::UserAgent->new(
137             (
138 0 0       0 $self->{show_progress} ? ( show_progress => 1 ) : (),
    0          
139             $self->ssl_opts ? ( ssl_opts => $self->ssl_opts ) : (),
140             )
141             );
142 0         0 return $self->{UserAgent};
143              
144             }
145              
146             =head2 get
147              
148             =cut
149              
150             sub get {
151 1     1 1 2 my ( $self, $path, $options, $callback ) = @_;
152 1         3 return $self->_hande_response( $self->user_agent->get( $self->uri( $path, %$options ) ) );
153             }
154              
155             =head2 delete
156              
157             =cut
158              
159             sub delete {
160 0     0 1 0 my ( $self, $path, $options, $callback ) = @_;
161 0         0 return $self->_hande_response( $self->user_agent->delete( $self->uri( $path, %$options ) ) );
162             }
163              
164             =head2 request
165              
166             =cut
167              
168             sub request {
169 0     0 1 0 my ( $self, $request, $callback ) = @_;
170 0         0 return $self->_hande_response( $self->user_agent->request( $request, $callback ) );
171             }
172              
173             =head2 post
174              
175             =cut
176              
177             sub post {
178 0     0 1 0 my ( $self, $path, $query, $body, $options, $callback ) = @_;
179 0 0       0 return $self->request( $self->_http_request( $path, $query ), $callback ) unless $body;
180 0 0       0 return $self->request( $self->_handle_json( $path, $query, $body ), $callback )
181             unless ($options);
182 0         0 return $self->request( $self->_handle_custom( $path, $query, $body, $options ), $callback );
183             }
184              
185             =head2 uri
186              
187             Creating a new URI object.
188              
189             Internal varibales:
190            
191             * scheme
192            
193             * authority
194              
195             Given varibales:
196            
197             * path
198            
199             * query options
200              
201             =cut
202              
203             sub uri {
204 1     1 1 2 my ( $self, $path, %opts ) = @_;
205 1         5 require URI;
206             my $uri =
207             URI->new(
208 1         4 $self->scheme() . $self->{_scheme_postfixes}->{ lc $self->scheme() } . $self->authority() . '/' . $path );
209 1         4740 $uri->query_form(%opts);
210 1         55 return $uri;
211             }
212              
213             =head2 to_hashref
214              
215             Getter/Setter for internal hash key ua.
216              
217             =cut
218              
219             sub to_hashref {
220 1     1 1 3 my ( $self, $content ) = @_;
221 1 50       5 return if !$content;
222 1         2 my $data = eval { $self->json->decode($content) };
  1         4  
223 1 50       14 return $@ ? $content : $data;
224 0         0 require Carp;
225 0         0 Carp::cluck;
226 0         0 Carp::croak "JSON ERROR: $@";
227             }
228              
229             {
230              
231             =head2 post
232              
233             =cut
234              
235             sub _handle_json {
236 0     0   0 my ( $self, $path, $query, $body ) = @_;
237 0         0 my $req = $self->_http_request( $path, $query );
238 0         0 $req->content_type('application/json');
239 0         0 my $json = $self->json->encode($body);
240 0         0 $json =~ s/"(false|true)"/$1/g;
241 0         0 $req->content($json);
242 0         0 return $req;
243             }
244              
245             =head2 post
246              
247             =cut
248              
249             sub _handle_custom {
250 0     0   0 my ( $self, $path, $query, $body, $options ) = @_;
251 0         0 my $req = $self->_http_request( $path, $query );
252 0         0 $req->content_type( $options->{content_type} );
253             $req->content_length(
254 3     3   1557 do { use bytes; length $body }
  3         24  
  3         12  
  0         0  
  0         0  
255             );
256 0         0 $req->content($body);
257 0         0 return $req;
258             }
259              
260             =head2 _http_request
261              
262             create HTTP::Request by uri params
263              
264             =cut
265              
266             sub _http_request {
267 0     0   0 my ( $self, $path, $query ) = @_;
268 0         0 require HTTP::Request;
269 0         0 return HTTP::Request->new( POST => $self->uri( $path, %$query ) );
270             }
271              
272             =head2 _hande_response
273              
274             =cut
275              
276             sub _hande_response {
277 1     1   17150 my ( $self, $response ) = @_;
278 1         3 $self->_error_code( $response->code, $response->message, $response->content );
279 1         3 my $content = $response->content();
280 1         11 return $self->to_hashref($content);
281             }
282              
283             =head2 _error_code
284              
285             Simple error handler returns undef if everything is ok dies on error.
286              
287             =cut
288              
289             sub _error_code {
290 1     1   25 my ( $self, $code, $message, $content ) = @_;
291 1 50       6 return $code if $self->{_valid_codes}->{$code};
292 0           require Carp;
293 0           Carp::cluck;
294 0           Carp::croak "FAILURE: $code - " . qq~$message\n$content~;
295             }
296             }
297              
298             1; # End of App::Docker::Client
299              
300             __END__