File Coverage

blib/lib/Net/Fastly.pm
Criterion Covered Total %
statement 41 210 19.5
branch 6 54 11.1
condition 3 21 14.2
subroutine 9 28 32.1
pod 14 14 100.0
total 73 327 22.3


line stmt bran cond sub pod time code
1             package Net::Fastly;
2              
3 4     4   289629 use strict;
  4         37  
  4         112  
4 4     4   21 use warnings;
  4         7  
  4         123  
5              
6 4     4   1832 use Net::Fastly::Client;
  4         16  
  4         158  
7 4     4   1739 use Net::Fastly::Invoice;
  4         12  
  4         26  
8 4     4   1887 use Net::Fastly::Settings;
  4         11  
  4         22  
9              
10             our $VERSION = "1.12";
11              
12             BEGIN {
13 4     4   206 no strict 'refs';
  4         8  
  4         766  
14 4     4   25 our @CLASSES = qw(Net::Fastly::User Net::Fastly::Customer
15             Net::Fastly::Backend Net::Fastly::Director
16             Net::Fastly::Domain Net::Fastly::Healthcheck
17             Net::Fastly::Match Net::Fastly::Origin
18             Net::Fastly::Service Net::Fastly::Syslog
19             Net::Fastly::VCL Net::Fastly::Version
20             Net::Fastly::Condition);
21              
22 4         12 foreach my $class (@CLASSES) {
23 52         142 my $file = $class . '.pm';
24 52         203 $file =~ s{::}{/}g;
25 52         22654 CORE::require($file);
26 52         429 $class->import;
27            
28 52         568 my $name = $class->_path;
29            
30 52         107 foreach my $method (qw(get create update delete list)) {
31 260         694 my $code = "sub { shift->_$method('$class', \@_) }";
32 260         442 my $glob = "${method}_${name}";
33 260 100       575 $glob .= "s" if $method eq 'list';
34             # don't create this if it's a list and something isn't listable ...
35 260 50 66     786 next if $method eq 'list' && $class->_skip_list;
36             # or if it already exists (i.e it's been overidden)
37 260 100       2352 next if defined *$glob;
38 256     0   16782 *$glob = eval "$code";
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
39             }
40             }
41             };
42              
43             =head1 NAME
44              
45             Net::Fastly - client library for interacting with the Fastly web acceleration service
46              
47             =head1 SYNOPSIS
48              
49             use Net::Fastly;
50              
51             # username/password authentication is deprecated and will not be available
52             # starting September 2020; use {api_key: 'your-key'} as the login option
53             my $fastly = Net::Fastly->new(%login_opts);
54            
55             my $current_user = $fastly->current_user;
56             my $current_customer = $fastly->current_customer;
57            
58             my $user = $fastly->get_user($current_user->id);
59             my $customer = $fastly->get_customer($current_customer->id);
60            
61             print "Name: ".$user->name."\n";
62             print "Works for ".$user->customer->name."\n";
63             print "Which is the same as ".$customer->name."\n";
64             print "Which has the owner ".$customer->owner->name."\n";
65            
66             # Let's see which services we have defined
67             foreach my $service ($fastly->list_services) {
68             print $service->name." (".$service->id.")\n";
69             foreach my $version ($service->versions) {
70             print "\t".$version->number."\n";
71             }
72             }
73            
74             my $service = $fastly->create_service(name => "MyFirstService");
75             my $latest_version = $service->version;
76            
77             # Create a domain and a backend for the service ...
78             my $domain = $fastly->create_domain(service_id => $service->id, version => $latest_version->number, name => "www.example.com");
79             my $backend = $fastly->create_backend(service_id => $service->id, version => $latest_version->number, ipv4 => "127.0.0.1", port => 80);
80            
81             # ... and activate it. You're now hosted on Fastly.
82             $latest_version->activate;
83            
84             # Let's take a peek at the VCL that Fastly generated for us
85             my $vcl = $latest_version->generated_vcl;
86             print "Generated VCL file is:\n".$vcl->content."\n";
87            
88             # Now let's create a new version ...
89             my $new_version = $latest_version->clone;
90             # ... add a new backend ...
91             my $new_backend = $fastly->create_backend(service_id => $service->id, version => $new_version->number, ipv4 => "192.0.0.1", port => 8080);
92             # ... and upload some custome vcl (presuming we have permissions)
93             $new_version->upload_vcl($vcl_name, slurp($vcl_file));
94            
95             $new_version->activate;
96              
97             # Purging
98             $fastly->purge('http://www.example.com'); # regular purge
99             $fastly->purge('http://www.example.com', 1); # 'soft' purge (see note below)
100             $service->purge_by_key('article-1'); # purge by surrogate key, note this works on $service
101             $service->purge_by_key('article-1', 1); # 'soft' purge by surrogate key
102             $service->purge_all; # use with caution!
103              
104             =head1 DESCRIPTION
105              
106             =head2 A Note About Authentication
107              
108             Authenticating with a username/password is deprecated and will no longer be available starting September 2020.
109              
110             Authenticating with an API Token is shown in the example synopsis below. For more information on API Tokens, please see [Fastly's API Token documentation](https://developer.fastly.com/reference/api/auth/). For more information about authenticating to our API, please see our [Authentication section](https://developer.fastly.com/reference/api/#authentication).
111              
112             =head1 METHODS
113              
114             =cut
115              
116              
117             =head2 new
118              
119             Create a new Fastly client. Options are
120              
121             =over 4
122              
123             =item user - your Fastly login
124              
125             =item password - your Fastly password
126              
127             =item api_key - your Fastly api key
128              
129             =back
130              
131             You only need to pass in C OR C and C.
132              
133             Some methods require full username and password rather than just auth token.
134              
135             =cut
136             sub new {
137 1     1 1 144 my $class = shift;
138 1         4 my %opts = @_;
139 1         9 my ($client, $user, $customer) = Net::Fastly::Client->new(%opts);
140 1         7 my $self = bless { _client => $client, _current_customer => undef, _current_user => undef}, $class;
141 1 50 33     5 if ($user && $customer) {
142 0         0 $self->{_current_user} = Net::Fastly::User->new($self, %$user);
143 0         0 $self->{_current_customer} = Net::Fastly::Customer->new($self, %$customer);
144             }
145 1         4 return $self;
146             }
147              
148             =head2 client
149              
150             Get the current Net::Fastly::Client
151              
152             =cut
153 0     0 1   sub client { shift->{_client} }
154              
155             =head2 set_customer
156              
157             Set the current customer to act as.
158              
159             B: this will only work if you're an admin
160              
161             =cut
162             sub set_customer {
163 0     0 1   my $self = shift;
164 0           my $id = shift;
165 0 0         die "You must be fully authed to set the customer" unless $self->fully_authed;
166 0 0         die "You must be an admin to set the customer" unless $self->current_user->can_do('admin');
167 0           delete $self->{_current_customer};
168 0           $self->client->set_customer($id);
169             }
170              
171             =head2 authed
172              
173             Whether or not we're authed at all by either username & password or API key
174              
175             =cut
176 0     0 1   sub authed { shift->client->authed }
177              
178             =head2 fully_authed
179              
180             Whether or not we're fully (username and password) authed
181              
182             =cut
183 0     0 1   sub fully_authed { shift->client->fully_authed }
184              
185             =head2 current_user
186              
187             Return a User object representing the current logged in user.
188              
189             This will not work if you're logged in with an API key.
190              
191             =cut
192             sub current_user {
193 0     0 1   my $self = shift;
194 0 0         die "You must be fully authed to get the current user" unless $self->fully_authed;
195 0   0       $self->{_current_user} ||= $self->_get("Net::Fastly::User");
196             }
197              
198             =head2 current_customer
199              
200             Return a Customer object representing the customer of the current logged in user.
201              
202             =cut
203             sub current_customer {
204 0     0 1   my $self = shift;
205 0 0         die "You must be authed to get the current customer" unless $self->authed;
206 0   0       $self->{_current_customer} ||= $self->_get("Net::Fastly::Customer");
207             }
208              
209             =head2 commands
210              
211             Return a hash representing all commands available.
212              
213             Useful for information.
214              
215             =cut
216             sub commands {
217 0     0 1   my $self = shift;
218 0 0         return $self->{__cache_commands} if ($self->{__cache_commands});
219 0           return eval { $self->{__cache_commands} = $self->client->_get('/commands') };
  0            
220             }
221              
222             =head2 purge [soft]
223              
224             Purge the specified path from your cache.
225              
226             You can optionally pass in a true value to enable "soft" purging e.g
227              
228             $fastly->purge($url, 1);
229              
230             See L
231              
232             Previously purging made an API call to the C endpoint of the Fastly API.
233              
234             The new method of purging is done by making an HTTP request against the URL using the C HTTP method.
235              
236             This module now uses the new method. The old method can be used by passing the C into the constructor.
237              
238             my $fastly = Net::Fastly->new(%login_opts, use_old_purge_method => 1);
239              
240             =cut
241             sub purge {
242 0     0 1   my $self = shift;
243 0           my $url = shift;
244 0           my $soft = shift;
245 0           $self->client->_purge($url, headers => { 'Fastly-Soft-Purge' => $soft });
246             }
247              
248             =head2 stats [opt[s]]
249              
250             Fetches historical stats for each of your fastly services and groups the results by service id.
251              
252             If you pass in a C opt then fetches only the specified field.
253              
254             If you pass in a C opt then fetches only the specified service.
255              
256             The C and C opts can be combined.
257              
258             If you pass in an C flag then fetches historical stats information aggregated across all of your Fastly services. This cannot be combined with C and C.
259              
260             Other options available are:
261              
262             =over 4
263              
264             =item from & to
265              
266             =item by
267              
268             =item region
269              
270             =back
271              
272             See http://docs.fastly.com/docs/stats for details.
273              
274             =cut
275             sub stats {
276 0     0 1   my $self = shift;
277 0           my %opts = @_;
278            
279 0 0 0       die "You can't specify a field or a service for an aggregate request" if $opts{aggregate} && ($opts{field} || $opts{service});
      0        
280            
281 0           my $url = "/stats";
282              
283 0 0         if (delete $opts{aggregate}) {
284 0           $url .= "/aggregate";
285             }
286            
287 0 0         if (my $service = delete $opts{service}) {
288 0           $url .= "/service/$service";
289             }
290            
291 0 0         if (my $field = delete $opts{field}) {
292 0           $url .= "/field/$field";
293             }
294            
295 0           $self->client->_get_stats($url, %opts);
296             }
297              
298              
299             =head2 usage [opt[s]]
300              
301             Returns usage information aggregated across all Fastly services and grouped by region.
302              
303             If the C flag is passed then teturns usage information aggregated by service and grouped by service & region.
304              
305             Other options available are:
306              
307             =over 4
308              
309             =item from & to
310              
311             =item by
312              
313             =item region
314              
315             =back
316              
317             See http://docs.fastly.com/docs/stats for details.
318              
319             =cut
320             sub usage {
321 0     0 1   my $self = shift;
322 0           my %opts = @_;
323            
324 0           my $url = "/stats/usage";
325 0 0         $url .= "_by_service" if delete $opts{by_service};
326            
327 0           $self->client->_get_stats($url, %opts);
328             }
329              
330              
331             =head2 regions
332              
333             Fetches the list of codes for regions that are covered by the Fastly CDN service.
334              
335             =cut
336             sub regions {
337 0     0 1   my $self = shift;
338 0           $self->client->_get_stats("/stats/regions");
339             }
340              
341              
342             =head2 create_user
343              
344             =head2 create_customer
345              
346             =head2 create_service
347              
348             =head2 create_version service_id => , [opts]
349              
350             =head2 create_backend service_id => , version => , name =>
351              
352             =head2 create_director service_id => , version => , name =>
353              
354             =head2 create_domain service_id => , version => , name =>
355              
356             =head2 create_healthcheck service_id => , version => , name =>
357              
358             =head2 create_match service_id => , version => , name =>
359              
360             =head2 create_origin service_id => , version => , name =>
361              
362             =head2 create_syslog service_id => , version => , name =>
363              
364             =head2 create_vcl service_id => , version => , name =>
365              
366             =head2 create_condition service_id => , version => , name =>
367              
368             Create new objects.
369              
370             =cut
371              
372             =head2 get_user
373              
374             =head2 get_customer
375              
376             =head2 get_service
377              
378             =head2 get_version
379              
380             =head2 get_backend
381              
382             =head2 get_director
383              
384             =head2 get_domain
385              
386             =head2 get_healthcheck
387              
388             =head2 get_invoice [ ]
389              
390             Return a Net::Fastly::Invoice objects representing an invoice for all services.
391              
392             If a year and month are passed in returns the invoice for that whole month.
393              
394             Otherwise it returns the invoices for the current month to date.
395              
396             =head2 get_match
397              
398             =head2 get_origin
399              
400             =head2 get_syslog
401              
402             =head2 get_vcl
403              
404             =head2 get_version
405              
406             =head2 get_settings
407              
408             =head2 get_condition
409              
410             Get existing objects.
411              
412             =cut
413              
414              
415             =head2 update_user
416              
417             =head2 update_customer
418              
419             =head2 update_service
420              
421             =head2 update_version
422              
423             =head2 update_backend
424              
425             =head2 update_director
426              
427             =head2 update_domain
428              
429             =head2 update_healthcheck
430              
431             =head2 update_match
432              
433             =head2 update_origin
434              
435             =head2 update_syslog
436              
437             =head2 update_vcl
438              
439             =head2 update_version
440              
441             =head2 update_settings
442              
443             =head2 update_condition
444              
445             Update existing objects.
446              
447             Note - you can also do
448              
449             $obj->save;
450              
451             =cut
452              
453              
454             =head2 delete_user
455              
456             =head2 delete_customer
457              
458             =head2 delete_service
459              
460             =head2 delete_version
461              
462             =head2 delete_backend
463              
464             =head2 delete_director
465              
466             =head2 delete_domain
467              
468             =head2 delete_healthcheck
469              
470             =head2 delete_match
471              
472             =head2 delete_origin
473              
474             =head2 delete_syslog
475              
476             =head2 delete_vcl
477              
478             =head2 delete_version
479              
480             =head2 delete_condition
481              
482             Delete existing objects.
483              
484             Note - you can also do
485              
486             $obj->delete
487              
488             =cut
489              
490              
491              
492             =head2 list_users
493              
494             =head2 list_customers
495              
496             =head2 list_versions
497              
498             =head2 list_services
499              
500             =head2 list_backends
501              
502             =head2 list_directors
503              
504             =head2 list_domains
505              
506             =head2 list_healthchecks
507              
508             =head2 list_matchs
509              
510             =head2 list_origins
511              
512             =head2 list_syslogs
513              
514             =head2 list_vcls
515              
516             =head2 list_versions
517              
518             =head2 list_conditions
519              
520             Get a list of all objects
521              
522             =head2 search_services
523              
524             Search all the services that the current customer has.
525              
526             In general you'll want to do
527              
528             my @services = $fastly->search_services(name => $name);
529              
530             or
531              
532             my ($service) = $fastly->search_services(name => $name, version => $number);
533              
534             =cut
535              
536 4     4   34 use Carp;
  4         6  
  4         3997  
537             sub _list {
538 0     0     my $self = shift;
539 0           my $class = shift;
540 0           my %opts = @_;
541 0           my $list = $self->client->_get($class->_list_path(%opts), %opts);
542 0 0         return () unless $list;
543 0           return map { $class->new($self, %$_) } @$list;
  0            
544             }
545              
546             sub _get {
547 0     0     my $self = shift;
548 0           my $class = shift;
549 0           my $hash;
550 0 0         if (@_) {
551 0           $hash = $self->client->_get($class->_get_path(@_));
552             } else {
553 0           $hash = $self->client->_get("/current_".$class->_path);
554             }
555 0 0         return undef unless $hash;
556 0           return $class->new($self, %$hash);
557             }
558              
559             sub _create {
560 0     0     my $self = shift;
561 0           my $class = shift;
562 0           my %args = @_;
563 0           my $hash = $self->client->_post($class->_post_path(%args), %args);
564 0           return $class->new($self, %$hash);
565             }
566              
567             sub _update {
568 0     0     my $self = shift;
569 0           my $class = shift;
570 0           my $obj = shift;
571 0           my %fds = $obj->_as_hash;
572 0           my $hash = $self->client->_put($class->_put_path($obj), map { $_ => $fds{$_} } grep { $_ !~ m/^(service_id|version)$/ } keys %fds);
  0            
  0            
573 0           return $class->new($self, %$hash);
574             }
575              
576             sub _delete {
577 0     0     my $self = shift;
578 0           my $class = shift;
579 0           my $obj = shift;
580 0 0         $obj = bless $obj, $class if 'HASH' eq ref($obj);
581 0           return defined $self->client->_delete($class->_delete_path($obj));
582             }
583              
584              
585             =head1 CLASS METHODS
586              
587             =head2 load_options
588              
589             Attempts to load various config options in the form
590              
591             =
592            
593             From a file.
594              
595             Skips whitespace and lines starting with C<#>.
596              
597             =cut
598              
599             sub load_options {
600 0     0 1   my $file = shift;
601 0           my %options = ();
602 0 0         return %options unless -f $file;
603              
604 0 0         open(my $fh, $file) || die "Couldn't open $file: $!\n";
605 0           while (<$fh>) {
606 0           chomp;
607 0 0         next if /^#/;
608 0 0         next if /^\s*$/;
609 0 0         next unless /=/;
610 0           s/(^\s*|\s*$)//g;
611 0           my ($key, $val) = split /\s*=\s*/, $_, 2;
612 0           $options{$key} = $val;
613             }
614 0           close($fh);
615 0           return %options;
616             }
617              
618             =head2 get_options
619              
620             Tries to load options from the file[s] passed in using,
621             C, stopping when it finds the first one.
622              
623             Then it overrides those options with command line options
624             of the form
625              
626             --=
627              
628             =cut
629             sub get_options {
630 0     0 1   my @configs = @_;
631 0           my %options;
632 0           foreach my $config (@configs) {
633 0 0         next unless -f $config;
634 0           %options = load_options($config);
635 0           last;
636             }
637 0   0       while (@ARGV && $ARGV[0] =~ m!^-+(\w+)\=(.+)$!) {
638 0 0         if ($1 eq "config") {
639 0 0         die "No such file '$2'" unless -f $2;
640 0           my %tmp = load_options($2);
641 0           $options{$_} = $tmp{$_} for keys %tmp;
642             } else {
643 0           $options{$1} = $2;
644             }
645 0           shift @ARGV;
646             }
647 0 0         die "Couldn't find options from command line arguments or ".join(", ", @configs)."\n" unless keys %options;
648 0           return %options;
649             }
650              
651             =head1 COPYRIGHT
652              
653             Copyright 2011 - Fastly Inc
654              
655             Distributed under the same terms as Perl itself.
656              
657             =head1 SUPPORT
658              
659             Mail support at fastly dot com if you have problems.
660              
661             =head1 DEVELOPERS
662              
663             http://github.com/fastly/fastly-perl
664              
665             http://www.fastly.com/documentation
666              
667             =cut
668             1;