diff -r 0f37544f1b98 -r aa1598910bb0 lib/DNS/Vi.pm --- a/lib/DNS/Vi.pm Fri May 23 16:15:41 2014 +0200 +++ b/lib/DNS/Vi.pm Sat May 24 23:01:17 2014 +0200 @@ -4,14 +4,16 @@ use warnings; use if $ENV{DEBUG}//'' eq 'dnsvi' => 'Smart::Comments'; use Digest::SHA qw(sha512_hex); +use File::Temp; use base 'Exporter'; -our @EXPORT = qw(ttl2h h2ttl parse delta nice); +our @EXPORT = qw(ttl2h h2ttl parse delta nice edit update show save); our @EXPORT_OK = (); sub parse { - my $data = join '', @_; + my %arg = %{pop @_} if ref $_[-1] eq 'HASH'; + my $data = shift; my @lines = split /\n/, $data; my @zone; @@ -42,6 +44,7 @@ rrtype => uc $+{rrtype}, data => $+{data}, ); + next if $rrset{rrtype} ~~ $arg{-skip}; if ($rrset{rrtype} eq 'SOA') { next if $soa_seen; @@ -117,8 +120,9 @@ return $out // $ttl; } +{ + my %order = map { state $n = 0; $_ => ++$n } qw(SOA NS TXT MX A AAAA); sub nice { - my %order = map { state $n = 0; $_ => ++$n } qw(SOA NS TXT MX A AAAA); # get a list of { id => $id, rrset => \%rrset } my @zone = @@ -155,9 +159,9 @@ $r{data}; }; push @out, $print->($_) foreach @zone; - return join "\n", @out; + return join "\n", @out, ''; } - +} sub delta { my ($zone1, $zone2) = @_; my %zone1 = map { $_->{id}, $_->{rrset} } @$zone1; @@ -174,4 +178,66 @@ return (\@add, \@del); } +sub edit { + my %arg = %{pop @_} if ref $_[-1] eq 'HASH'; + my @zone = @_; + + my $tmp = File::Temp->new(); + $tmp->print(nice @zone); + $tmp->flush(); + system $arg{-editor} => $tmp->filename; + $tmp->seek(0, 0); + return parse(do { local $/ = undef; <$tmp>}, {-skip => $arg{-skip}}); +} + +sub show { + my ($add, $del) = @_; + my @out = ( + (map { " - $_ " } @$del), + (map { " + $_ " } @$add), + ); + return @out; +} + +sub update { + my %arg = %{pop @_} if ref $_[-1] eq 'HASH'; + my ($zone1, $add, $del) = @_; + + my $orig_soa = + (grep { $_->{rrtype} eq 'SOA' } map { $_->{rrset} } @$zone1)[0]; + + my @cmds = ( + $arg{-local} ? () : "server $arg{-server}", + "prereq yxrrset @{$orig_soa}{qw{label rrtype data}}", + (map { "update delete $_" } @$del), + (map { "update add $_" } @$add), + 'show', + 'send', + 'answer', + ); + my @nsupdate = ( + 'nsupdate', + defined $arg{-debug} ? ('-d') : (), + defined $arg{-key} ? (-k => $arg{-key}) : (), + defined $arg{-local} ? ('-l') : (), + ); + + open(my $nsupdate, '|-') or do { + exec @nsupdate; + die "Can't exec @nsupdate: $!\n"; + }; + say $nsupdate join "\n", @cmds; + close($nsupdate); + say "nsupdate returned $?"; + return $? ? undef : 1; +} + +sub save { + my ($zone, $file) = @_; + open(my $fh, '>', $file) or die "Can't open >$file: $!\n"; + print $fh nice @$zone; + close($fh); + +} + 1;