1use strict; 2use warnings; 3 4package Net::Amazon::Route53::HostedZone; 5{ 6 $Net::Amazon::Route53::HostedZone::VERSION = '0.122310'; 7} 8use Mouse; 9use HTML::Entities; 10 11use Net::Amazon::Route53::Change; 12use Net::Amazon::Route53::ResourceRecordSet; 13 14=head2 SYNOPSIS 15 16 my $hostedzone = Net::Amazon::Route53::HostedZone->new(...); 17 # use methods on $hostedzone 18 19=cut 20 21=head2 ATTRIBUTES 22 23=cut 24 25=head3 route53 26 27A L<Net::Amazon::Route53> object, needed and used to perform requests 28to Amazon's Route 53 service 29 30=cut 31 32has 'route53' => (is => 'rw', isa => 'Net::Amazon::Route53', required => 1,); 33 34=head3 id 35 36The hosted zone's id 37 38=head3 name 39 40The hosted zone's name; ends in a dot, i.e. 41 42 example.com. 43 44=head3 callerreference 45 46The CallerReference attribute for the hosted zone 47 48=head3 comment 49 50Any Comment given when the zone is created 51 52=cut 53 54has 'id' => (is => 'rw', isa => 'Str', required => 1, default => ''); 55has 'name' => (is => 'rw', isa => 'Str', required => 1, default => ''); 56has 'callerreference' => 57 (is => 'rw', isa => 'Str', required => 1, default => ''); 58has 'comment' => (is => 'rw', isa => 'Str', required => 1, default => ''); 59 60=head3 nameservers 61 62Lazily loaded, returns a list of the nameservers authoritative for this zone 63 64=cut 65 66has 'nameservers' => ( 67 is => 'rw', 68 isa => 'ArrayRef[Str]', 69 lazy => 1, 70 default => sub { 71 my $self = shift; 72 my $resp = $self->route53->request('get', 73 'https://route53.amazonaws.com/2010-10-01/' . $self->id); 74 my @nameservers = 75 map {decode_entities($_)} 76 @{ $resp->{DelegationSet}{NameServers}{NameServer} }; 77 \@nameservers; 78 }); 79 80=head3 resource_record_sets 81 82Lazily loaded, returns a list of the resource record sets 83(L<Net::Amazon::Route53::ResourceRecordSet> objects) for this zone. 84 85=cut 86 87has 'resource_record_sets' => ( 88 is => 'rw', 89 isa => 'ArrayRef', 90 lazy => 1, 91 default => sub { 92 my $self = shift; 93 my $next_record_name = ''; 94 my @resource_record_sets; 95 while (1) { 96 my $resp = $self->route53->request('get', 97 'https://route53.amazonaws.com/2010-10-01/' 98 . $self->id 99 . '/rrset?maxitems=100' 100 . $next_record_name); 101 my $set = $resp->{ResourceRecordSets}{ResourceRecordSet}; 102 my @results = ref($set) eq 'ARRAY' ? @$set : ($set); 103 for my $res (@results) { 104 push @resource_record_sets, 105 Net::Amazon::Route53::ResourceRecordSet->new( 106 route53 => $self->route53, 107 hostedzone => $self, 108 name => decode_entities($res->{Name}), 109 ttl => $res->{TTL} || 0, 110 type => decode_entities($res->{Type}), 111 values => [ 112 map {decode_entities($_->{Value})} @{ 113 ref $res->{ResourceRecords}{ResourceRecord} eq 114 'ARRAY' 115 ? $res->{ResourceRecords}{ResourceRecord} 116 : [ $res->{ResourceRecords}{ResourceRecord} ] } 117 ], 118 ); 119 } 120 last unless $resp->{NextRecordName}; 121 $next_record_name = '&name=' . $resp->{NextRecordName}; 122 } 123 \@resource_record_sets; 124 }); 125 126=head2 METHODS 127 128=cut 129 130=head3 create 131 132Creates a new zone. Needs all the attributes (name, callerreference and comment). 133 134Takes an optional boolean parameter, C<wait>, to indicate whether the request should 135return straightaway (default, or when C<wait> is C<0>) or it should wait until the 136request is C<INSYNC> according to the Change's status. 137 138Returns a L<Net::Amazon::Route53::Change> object representing the change requested. 139 140=cut 141 142sub create { 143 my $self = shift; 144 my $wait = shift; 145 $wait = 0 if !defined $wait; 146 $self->name =~ /\.$/ 147 or die "Zone name needs to end in a dot, to be created\n"; 148 my $request_xml_str = <<'ENDXML'; 149<?xml version="1.0" encoding="UTF-8"?> 150<CreateHostedZoneRequest xmlns="https://route53.amazonaws.com/doc/2010-10-01/"> 151 <Name>%s</Name> 152 <CallerReference>%s</CallerReference> 153 <HostedZoneConfig> 154 <Comment>%s</Comment> 155 </HostedZoneConfig> 156</CreateHostedZoneRequest> 157ENDXML 158 my $request_xml = sprintf($request_xml_str, 159 map {$_} $self->name, 160 $self->callerreference, $self->comment); 161 my $resp = $self->route53->request( 162 'post', 163 'https://route53.amazonaws.com/2010-10-01/hostedzone', 164 'content-type' => 'text/xml; charset=UTF-8', 165 Content => $request_xml, 166 ); 167 $self->id($resp->{HostedZone}{Id}); 168 my $change = Net::Amazon::Route53::Change->new( 169 route53 => $self->route53, 170 ( 171 map {lc($_) => decode_entities($resp->{ChangeInfo}{$_})} 172 qw/Id Status SubmittedAt/ 173 ), 174 ); 175 $change->refresh(); 176 return $change if !$wait; 177 178 while (lc($change->status) ne 'insync') { 179 sleep 2; 180 $change->refresh(); 181 } 182 return $change; 183} 184 185=head3 delete 186 187Deletes the zone. A zone can only be deleted by Amazon's Route 53 service if it 188contains no records other than a SOA or NS. 189 190Takes an optional boolean parameter, C<wait>, to indicate whether the request should 191return straightaway (default, or when C<wait> is C<0>) or it should wait until the 192request is C<INSYNC> according to the Change's status. 193 194Returns a L<Net::Amazon::Route53::Change> object representing the change requested. 195 196=cut 197 198sub delete { 199 my $self = shift; 200 my $wait = shift; 201 $wait = 0 if !defined $wait; 202 my $resp = 203 $self->route53->request('delete', 204 'https://route53.amazonaws.com/2010-10-01/' . $self->id, 205 ); 206 my $change = Net::Amazon::Route53::Change->new( 207 route53 => $self->route53, 208 ( 209 map {lc($_) => decode_entities($resp->{ChangeInfo}{$_})} 210 qw/Id Status SubmittedAt/ 211 ), 212 ); 213 $change->refresh(); 214 return $change if !$wait; 215 while (lc($change->status) ne 'insync') { 216 sleep 2; 217 $change->refresh(); 218 } 219 return $change; 220} 221 222no Mouse; 223 224=head1 AUTHOR 225 226Marco FONTANI <mfontani@cpan.org> 227 228=head1 COPYRIGHT AND LICENSE 229 230This software is copyright (c) 2011 by Marco FONTANI. 231 232This is free software; you can redistribute it and/or modify it under 233the same terms as the Perl 5 programming language system itself. 234 235=cut 236 2371; 238