File Coverage

blib/lib/Net/Dynect/REST/Zone.pm
Criterion Covered Total %
statement 12 138 8.7
branch 0 78 0.0
condition 0 16 0.0
subroutine 4 17 23.5
pod 11 12 91.6
total 27 261 10.3


line stmt bran cond sub pod time code
1             package Net::Dynect::REST::Zone;
2             # $Id: Zone.pm 149 2010-09-26 01:33:15Z james $
3 1     1   4233 use strict;
  1         2  
  1         46  
4 1     1   6 use warnings;
  1         3  
  1         54  
5 1     1   5 use overload '""' => \&_as_string;
  1         2  
  1         12  
6 1     1   84 use Carp;
  1         3  
  1         2491  
7             our $VERSION = do { my @r = (q$Revision: 149 $ =~ /\d+/g); sprintf "%d."."%03d" x $#r, @r };
8              
9             sub new {
10 0     0 1   my $proto = shift;
11 0   0       my $self = bless {}, ref($proto) || $proto;
12 0           my %args = @_;
13 0 0         $self->{connection} = $args{connection} if defined $args{connection};
14 0 0         $self->get( $args{zone} ) if defined $args{zone};
15 0           return $self;
16             }
17              
18             sub get {
19 0     0 1   my $self = shift;
20 0           my $zone = shift;
21 0           my $request = Net::Dynect::REST::Request->new(
22             operation => 'read',
23             service => "Zone/$zone"
24             );
25 0           my $response = $self->{connection}->execute($request);
26 0           $self->last_response($response);
27 0 0         if ( $response->status !~ /^success$/i ) {
28 0           carp $response->msg->[0]->info;
29 0           return;
30             }
31 0           $self->name($zone);
32 0           $self->serial( $response->data->serial );
33 0           $self->serial_style( $response->data->serial_style );
34 0           $self->zone_type( $response->data->zone_type );
35 0           return 1;
36             }
37              
38             sub save {
39 0     0 1   my $self = shift;
40 0           my %args = @_;
41 0 0         return unless defined $self->{connection};
42 0 0         return unless defined $self->name;
43 0 0         if ( not defined $args{rname} ) {
44 0           print "Need an rname (admin email) for the zone.\n";
45 0           return;
46             }
47 0 0         if ( defined $self->serial ) {
48 0           print "Zone already has a serial? Aborting.\n";
49 0           return;
50             }
51              
52 0   0       my $request = Net::Dynect::REST::Request->new(
      0        
53             operation => 'create',
54             service => "Zone/" . $self->name,
55             params => {
56             zone => $self->name,
57             ttl => $args{ttl} || 3600,
58             rname => $args{rname}
59             },
60             serial_style => $args{serial_style}
61             || $self->serial_style
62             || 'increment',
63             zone_type => $self->zone_type
64             );
65 0           my $response = $self->{connection}->execute($request);
66 0           $self->last_response($response);
67 0 0         return unless $response->status =~ /^success$/i;
68 0           $self->serial( $response->data->serial );
69 0           $self->serial_style( $response->data->serial_style );
70 0           $self->zone_type( $response->data->zone_type );
71 0           return 1;
72             }
73              
74             sub delete {
75 0     0 1   my $self = shift;
76 0 0         return unless defined $self->{connection};
77 0 0 0       return unless defined $self->name && $self->serial;
78 0           my $request = Net::Dynect::REST::Request->new(
79             operation => 'delete',
80             service => 'Zone/' . $self->name
81             );
82 0           my $response = $self->{connection}->execute($request);
83 0           $self->last_response($response);
84 0 0         if ( $response->status =~ /^success$/i ) {
85 0           $self->{name} = undef;
86 0           $self->{serial} = undef;
87 0           $self->{serial_style} = undef;
88 0           $self->{zone_type} = undef;
89 0           $self = undef;
90 0           return 1;
91             }
92             else {
93 0           print $response->msg->[0]->info;
94             }
95             }
96              
97             sub freeze {
98 0     0 1   my $self = shift;
99 0 0         return unless defined $self->{connection};
100 0 0 0       return unless defined $self->name && $self->serial;
101 0           my $request = Net::Dynect::REST::Request->new(
102             operation => 'update',
103             service => 'Zone/' . $self->name,
104             params => { freeze => 1 }
105             );
106 0           my $response = $self->{connection}->execute($request);
107 0           $self->last_response($response);
108 0 0         if ( $response->status =~ /^success$/i ) {
109 0 0         $self->serial( $response->data->serial )
110             if defined $response->data->serial;
111 0 0         $self->serial_style( $response->data->serial_style )
112             if defined $response->data->serial_style;
113 0 0         $self->zone_type( $response->data->zone_type )
114             if defined $response->data->zone_type;
115 0           return 1;
116             }
117             }
118              
119             sub thaw {
120 0     0 1   my $self = shift;
121 0 0         return unless defined $self->{connection};
122 0 0 0       return unless defined $self->name && $self->serial;
123 0           my $request = Net::Dynect::REST::Request->new(
124             operation => 'update',
125             service => 'Zone/' . $self->name,
126             params => { thaw => 1 }
127             );
128 0           my $response = $self->{connection}->execute($request);
129 0           $self->last_response($response);
130 0 0         if ( $response->status =~ /^success$/i ) {
131 0 0         $self->serial( $response->data->serial )
132             if defined $response->data->serial;
133 0 0         $self->serial_style( $response->data->serial_style )
134             if defined $response->data->serial_style;
135 0           return 1;
136             }
137             }
138              
139             sub publish {
140 0     0 1   my $self = shift;
141 0 0         return unless defined $self->{connection};
142 0 0         return unless defined $self->name;
143 0           my $request = Net::Dynect::REST::Request->new(
144             operation => 'update',
145             service => 'Zone/' . $self->name,
146             params => { publish => 1 }
147             );
148 0           my $response = $self->{connection}->execute($request);
149 0           $self->last_response($response);
150 0 0         if ( $response->status =~ /^success$/i ) {
151 0           return 1;
152             }
153             }
154              
155             sub name {
156 0     0 1   my $self = shift;
157 0 0         if (@_) {
158 0           my $new = shift;
159 0 0         if ( defined $self->{name} ) {
    0          
160 0           carp
161             "Cannot change name from what it has been set to. Create a new instance for a new zone, and delete the old one";
162 0           return;
163             }
164             elsif ( $new !~ /^\S+/ ) {
165 0           carp "Zone names must not have spaces in them";
166 0           return;
167             }
168 0           $self->{name} = $new;
169             }
170 0           return $self->{name};
171             }
172              
173             sub serial {
174 0     0 1   my $self = shift;
175 0 0         if (@_) {
176 0           my $new = shift;
177 0 0         if ( $new !~ /^\d+$/ ) {
178 0           carp "Serial should only be numeric";
179 0           return;
180             }
181 0           $self->{serial} = $new;
182             }
183 0           return $self->{serial};
184             }
185              
186             sub serial_style {
187 0     0 1   my $self = shift;
188 0 0         if (@_) {
189 0           my $new = shift;
190 0 0         if ( $new !~ /^increment|epoch|day|minute$/i ) {
191 0           carp
192             "Serial style can only be one of: increment, epoch, day, minute";
193 0           return;
194             }
195 0           $self->{serial_style} = lc $new;
196             }
197 0           return $self->{serial_style};
198             }
199              
200             sub zone_type {
201 0     0 1   my $self = shift;
202 0 0         if (@_) {
203 0           my $new = shift;
204 0 0         if ( $new !~ /^Primary|Secondary$/ ) {
205 0           carp "Zone type can only be one of: Primary, Secondary";
206 0           return;
207             }
208 0           $self->{zone_type} = $new;
209             }
210 0           return $self->{zone_type};
211             }
212              
213             sub last_response {
214 0     0 0   my $self = shift;
215 0 0         if (@_) {
216 0           my $new = shift;
217 0           $self->{last_response} = $new;
218             }
219 0           return $self->{last_response};
220             }
221              
222             sub _as_string {
223 0     0     my $self = shift;
224 0           my @texts;
225 0 0         push @texts, sprintf "Zone '%s'", $self->name if defined $self->name;
226 0 0         push @texts, sprintf "Zone Type '%s'", $self->zone_type
227             if defined $self->zone_type;
228 0 0         push @texts, sprintf "Serial '%s'", $self->serial if defined $self->serial;
229 0 0         push @texts, sprintf "Serial Style '%s'", $self->serial_style
230             if defined $self->serial_style;
231 0           return join( ', ', @texts );
232             }
233              
234             1;
235              
236             =head1 NAME
237              
238             Net::Dynect::REST::Zone - A DNS zone object
239              
240             =head1 SYNOPSIS
241              
242             use Net::Dynect::REST;
243             use Net::Dynect::REST::Zone;
244             $dynect = Net::Dynect::REST->new(user_name => 'me', customer_name => 'myco', password => 'secret');
245             $zone = Net::Dynect::REST::Zone->new(connection => $dynect, zone => 'example.com');
246             print "Zone details: $zone\n";
247              
248             $zone->freeze;
249             $zone->thaw;
250             $zone->publish;
251             $zone->delete;
252              
253             $new_zone = Net::Dynect::REST::Zone->new(connection => $dynect);
254             $zone->name('new.example.com');
255             $zone->serial_style('increment');
256             $zone->zone_type('Primary');
257             $zone->save(rname => 'admin@example.com', ttl => 900);
258              
259             =head1 REQUIRES
260              
261             Net::Dynect::REST, Carp
262              
263             =head1 EXPORTS
264              
265             Nothing
266              
267             =head1 Description
268              
269             A Net::Dynect::REST::Zone is a representation of a DNS Zone in the Dynect REST interface. It permits the user to load zones that already exist, inspect their attributes (eg, serial number), freeze the zone from modification, thaw the zone, publish zone changes live, delete the zone, and create a new zone.
270              
271             =head1 METHODS
272              
273             =head2 Creation
274              
275             =over 4
276              
277             =item Net::Dynect::REST::Zone->new(connection => $dynect)
278              
279             Creates and returns a Net::Dynect::REST::Zone object. You should pass this method your connection object, which should have a valid session established, in order to do anything useful.
280              
281             =back
282              
283             =head2 Operations
284              
285             =over 4
286              
287             =item $zone->get('zone.to.get.com');
288              
289             This will attempt to get the details of the zone from Dynect.
290              
291             =item $zone->save(rname => 'admin@example.com', ttl => 900);
292              
293             This will try to save a new zone (which has already had its name and serial style set via the L below). You must supply the "I" parameter of the email address for the resposible person, and you may supply a I value.
294              
295              
296             =item $zone->delete();
297              
298             This will tryt o delete the zone that was previously loaded.
299              
300             =item $zone->freeze();
301              
302             This will freeze the zone from any changes.
303              
304             =item $zone->thaw();
305              
306             This will unfreeze the zone and permit changes.
307              
308             =item $zone->publish();
309              
310             This will commit changes to the zone to the live production environment.
311              
312             =back
313              
314             =head2 Attributes
315              
316             =over 4
317              
318             =item $zone->name();
319              
320             This will get (or set) the zone's name, eg: example.com.
321              
322             =item $zone->serial();
323              
324             This will get (or set) the zones serial number.
325              
326             =item $zone->zone_type();
327              
328             This will get (or set) the zone type, either:
329              
330             =over 4
331              
332             =item * Primary
333              
334             =item * Secondary
335              
336             =back
337              
338             =item $zone->serial_style();
339              
340             This will get or set the serial style for the zone, either
341              
342             =over 4
343              
344             =item * increment
345              
346             =item * epoch
347              
348             =item * day
349              
350             =item * minute
351              
352             =back
353              
354             =back
355              
356             =head1 AUTHOR
357              
358             James Bromberger, james@rcpt.to
359              
360             =head1 SEE ALSO
361              
362             L, L, L, L.
363              
364             =head1 COPYRIGHT AND LICENSE
365              
366             Copyright (C) 2010 by James Bromberger
367              
368             This library is free software; you can redistribute it and/or modify
369             it under the same terms as Perl itself, either Perl version 5.10.1 or,
370             at your option, any later version of Perl 5 you may have available.
371              
372              
373              
374              
375             =cut