File Coverage

blib/lib/WebService/Rackspace/CloudFiles/Container.pm
Criterion Covered Total %
statement 18 103 17.4
branch 0 36 0.0
condition 0 6 0.0
subroutine 6 18 33.3
pod 10 10 100.0
total 34 173 19.6


line stmt bran cond sub pod time code
1             package WebService::Rackspace::CloudFiles::Container;
2 3     3   23 use Moo;
  3         9  
  3         30  
3 3     3   1226 use MooX::StrictConstructor;
  3         9  
  3         31  
4 3     3   3421 use Types::Standard qw(Bool Str Num Int HashRef InstanceOf);
  3         8  
  3         34  
5 3     3   5245 use WebService::Rackspace::CloudFiles::Object::Iterator;
  3         11  
  3         122  
6 3     3   614 use JSON::Any;
  3         3746  
  3         33  
7 3     3   5264 use Carp qw(confess);
  3         8  
  3         4404  
8            
9             has 'cloudfiles' =>
10             ( is => 'ro', isa => InstanceOf['WebService::Rackspace::CloudFiles'], required => 1 );
11             has 'name' => (is => 'ro', isa => Str, required => 1);
12             has 'cdn_enabled' => (is => 'rw', isa => Bool);
13             has 'ttl' => (is => 'rw', isa => Num);
14             has 'log_retention' => (is => 'rw', isa => Str);
15             has 'cdn_uri' => (is => 'rw', isa => Str);
16             has 'cdn_ssl_uri' => (is => 'rw', isa => Str);
17             has 'cdn_streaming_uri' => (is => 'rw', isa => Str);
18             has 'bytes' => (is => 'rw', isa => Num);
19             has 'count' => (is => 'rw', isa => Num);
20              
21             __PACKAGE__->meta->make_immutable;
22              
23             sub _url {
24 0     0     my ( $self, $url_type ) = @_;
25              
26 0   0       $url_type ||= '';
27 0 0         my $storage_url = $url_type eq 'cdn' ? 'cdn_management_url' : 'storage_url';
28 0           my $url = $self->cloudfiles->$storage_url . '/' . $self->name;
29 0           utf8::downgrade($url);
30 0           return $url;
31             }
32              
33             sub cdn_init {
34 0     0 1   my $self = shift;
35            
36 0           my $response = $self->head('cdn');
37 0           my $cdn_enabled = $response->header('X-CDN-Enabled');
38 0 0         $self->cdn_enabled(ref $cdn_enabled eq ref JSON::Any->true ? 1 : 0 );
39 0           $self->ttl( $response->header('X-TTL') );
40 0           $self->log_retention( $response->header('X-Log-Retention') );
41 0           $self->cdn_uri( $response->header('X-CDN-URI') );
42 0           $self->cdn_ssl_uri( $response->header('X-CDN-SSL-URI') );
43 0           $self->cdn_streaming_uri( $response->header('X-CDN-STREAMING-URI') );
44             }
45              
46             sub cdn_enable {
47 0     0 1   my ($self, $ttl, $log_retention) = @_;
48 0   0       $ttl ||= 259200;
49 0   0       $log_retention ||= 0;
50 0 0         my $request = HTTP::Request->new('PUT', $self->_url('cdn'),
51             [ 'X-Auth-Token' => $self->cloudfiles->token,
52             'X-CDN-Enabled' => 'True',
53             'X-TTL' => $ttl,
54             'X-Log-Retention' => $log_retention ? 'True' : 'False' ] );
55 0           my $response = $self->cloudfiles->_request($request);
56 0 0         confess 'Unknown error' unless $response->is_success;
57              
58 0           $self->ttl( $ttl );
59 0           $self->log_retention( $log_retention );
60 0           $self->cdn_uri( $response->header('X-CDN-URI') );
61 0           $self->cdn_ssl_uri( $response->header('X-CDN-SSL-URI') );
62             }
63              
64             sub cdn_disable {
65 0     0 1   my $self = shift;
66 0           my $request = HTTP::Request->new('POST', $self->_url('cdn'),
67             [ 'X-Auth-Token' => $self->cloudfiles->token,
68             'X-CDN-Enabled' => 'False' ] );
69 0           my $response = $self->cloudfiles->_request($request);
70 0 0         confess 'Unknown error' unless $response->is_success;
71              
72 0           $self->ttl( 0 );
73 0           $self->log_retention( 0 );
74 0           $self->cdn_uri( $response->header('X-CDN-URI') );
75 0           $self->cdn_ssl_uri( $response->header('X-CDN-SSL-URI') );
76             }
77              
78             sub head {
79 0     0 1   my ($self, $url) = @_;
80 0           my $request = HTTP::Request->new('HEAD', $self->_url($url),
81             [ 'X-Auth-Token' => $self->cloudfiles->token ] );
82 0           my $response = $self->cloudfiles->_request($request);
83 0 0         confess 'Unknown error' unless $response->is_success;
84 0           return $response;
85             }
86              
87             sub object_count {
88 0     0 1   my $self = shift;
89 0           my $response = $self->head;
90 0           return $response->header('X-Container-Object-Count');
91             }
92              
93             sub bytes_used {
94 0     0 1   my $self = shift;
95 0           my $response = $self->head;
96 0           return $response->header('X-Container-Bytes-Used');
97             }
98              
99             sub delete {
100 0     0 1   my $self = shift;
101 0           my $request = HTTP::Request->new( 'DELETE', $self->_url,
102             [ 'X-Auth-Token' => $self->cloudfiles->token ] );
103 0           my $response = $self->cloudfiles->_request($request);
104 0 0         confess 'Not empty' if $response->code == 409;
105 0 0         confess 'Unknown error' if !$response->is_success;
106             }
107              
108             sub purge_cdn {
109 0     0 1   my ($self, @emails) = @_;
110 0           my $request = HTTP::Request->new( 'DELETE', $self->_url('cdn'),
111             [ 'X-Auth-Token' => $self->cloudfiles->token,
112             'X-Purge-Email' => join ', ', @emails] );
113 0           my $response = $self->cloudfiles->_request($request);
114 0 0         confess 'Not Found' if $response->code == 404;
115 0 0         confess 'Unauthorized request' if $response->code == 403;
116 0 0         confess 'Unknown error' if !$response->is_success;
117             }
118              
119             sub objects {
120 0     0 1   my ( $self, %args ) = @_;
121              
122 0           my $limit = 10_000;
123 0           my $marker;
124 0           my $prefix = $args{prefix};
125 0           my $finished = 0;
126              
127             return $self->cloudfiles->iterator_callback_class->new(
128             callback => sub {
129 0 0   0     return undef if $finished;
130              
131 0           my $url = URI->new( $self->_url );
132 0           $url->query_param( 'limit', $limit );
133 0           $url->query_param( 'marker', $marker );
134 0           $url->query_param( 'prefix', $prefix );
135 0           $url->query_param( 'format', 'json' );
136 0           my $request = HTTP::Request->new( 'GET', $url,
137             [ 'X-Auth-Token' => $self->cloudfiles->token ] );
138 0           my $response = $self->cloudfiles->_request($request);
139 0 0         return if $response->code == 204;
140 0 0         confess 'Unknown error' if !$response->is_success;
141 0 0         return undef unless $response->content;
142 0           my @objects;
143              
144 0           my @bits = @{ JSON::Any->jsonToObj( $response->content ) };
  0            
145 0 0         return unless @bits;
146 0           foreach my $bit (@bits) {
147             push @objects,
148             WebService::Rackspace::CloudFiles::Object->new(
149             cloudfiles => $self->cloudfiles,
150             container => $self,
151             name => $bit->{name},
152             etag => $bit->{hash},
153             size => $bit->{bytes},
154             content_type => $bit->{content_type},
155             last_modified => $bit->{last_modified},
156 0           );
157             }
158              
159 0 0         if ( @bits < $limit ) {
160 0           $finished = 1;
161             } else {
162 0           $marker = $objects[-1]->name;
163             }
164              
165 0           return \@objects;
166             }
167 0           );
168             }
169              
170             sub object {
171 0     0 1   my ( $self, %conf ) = @_;
172 0 0         confess 'Missing name' unless $conf{name};
173 0           return WebService::Rackspace::CloudFiles::Object->new(
174             cloudfiles => $self->cloudfiles,
175             container => $self,
176             %conf,
177             );
178             }
179              
180             1;
181              
182             __END__
183              
184             =head1 NAME
185              
186             WebService::Rackspace::CloudFiles::Container - Represent a Cloud Files container
187              
188             =head1 DESCRIPTION
189              
190             This class represents a container in Cloud Files. It is created by
191             calling new_container or container on a L<WebService::Rackspace::CloudFiles> object.
192              
193             =head1 METHODS
194              
195             =head2 name
196              
197             Returns the name of the container:
198              
199             say 'have container ' . $container->name;
200              
201             =head2 cdn_enabled
202              
203             Return true if the container is public.
204              
205             =head2 ttl
206              
207             The TTL (Time To Live) of the container and its objects.
208              
209             =head2 log_retention
210              
211             =head2 cdn_uri
212              
213             HTTP CDN URL to container, only applies when the container is public.
214              
215             =head2 cdn_ssl_uri
216              
217             HTTPS CDN URL to container, only applies when the container is public.
218              
219             =head2 cdn_init
220              
221             Retrieve CDN settings if the container is public.
222              
223             =head2 cdn_enable($ttl, $log_retention)
224              
225             Enable CDN to make contents of container public. I<$ttl> Defaults to 72-hours
226             and I<$log_retention> defaults to false.
227              
228             =head2 cdn_disable
229              
230             Disable the CDN enabled container. Doesn't purge objects from CDN which means
231             that they'll be available until their TTL expires.
232              
233             =head2 head
234              
235             Perform a HEAD request.
236              
237             =head2 object_count
238              
239             Returns the total number of objects in the container:
240              
241             my $object_count = $container->object_count;
242              
243             =head2 bytes_used
244              
245             Returns the total number of bytes used by objects in the container:
246              
247             my $bytes_used = $container->bytes_used;
248              
249             =head2 objects
250              
251             Returns a list of objects in the container as
252             L<WebService::Rackspace::CloudFiles::Object> objects. As the API only returns
253             ten thousand objects per request, this module may have to do multiple
254             requests to fetch all the objects in the container. This is exposed
255             by using a L<Rackspace::CloudFiles::Object::Iterator> object. You can also pass
256             in a prefix:
257              
258             foreach my $object ($container->objects->all) {
259             ...
260             }
261              
262             my @objects = $container->objects(prefix => 'dir/')->all;
263              
264             =head2 object
265              
266             This returns a L<WebService::Rackspace::CloudFiles::Object> representing
267             an object.
268              
269             my $xxx = $container->object( name => 'XXX' );
270             my $yyy = $container->object( name => 'YYY', content_type => 'text/plain' );
271              
272             =head2 delete
273              
274             Deletes the container, which should be empty:
275              
276             $container->delete;
277              
278             =head2 purge_cdn
279              
280             Purges a CDN enabled container without having to wait for the TTL to expire.
281              
282             $container->purge_cdn;
283              
284             Purging a CDN enabled container may take a very long time. So you can optionally
285             provide one or more emails to be notified after the container is fully purged.
286              
287             my @emails = ('foo@example.com', 'bar@example.com');
288             $container->purge_cdn(@emails);
289              
290             =head2 cloudfiles
291              
292             =head1 SEE ALSO
293              
294             L<WebService::Rackspace::CloudFiles>, L<WebService::Rackspace::CloudFiles::Object>.
295              
296             =head1 AUTHORS
297              
298             Christiaan Kras <ckras@cpan.org>.
299             Leon Brocard <acme@astray.com>.
300              
301             =head1 COPYRIGHT
302              
303             Copyright (C) 2010-2011, Christiaan Kras
304             Copyright (C) 2008-9, Leon Brocard
305              
306             =head1 LICENSE
307              
308             This module is free software; you can redistribute it or modify it
309             under the same terms as Perl itself.