Created
December 13, 2010 20:59
-
-
Save wizardishungry/739596 to your computer and use it in GitHub Desktop.
[broken] Using Linode DNS Manager for Google Apps http://blog.pathennessy.org/2008/12/08/using-linode-dns-manager-for-google-apps/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# | |
# googleapps-dns.pl | |
# | |
# Script to populate the Linode's DNS Manager for Google Apps. | |
# | |
# Copyright (c) 2008 Patrick Hennessy | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a copy | |
# of this software and associated documentation files (the "Software"), to deal | |
# in the Software without restriction, including without limitation the rights | |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
# copies of the Software, and to permit persons to whom the Software is | |
# furnished to do so, subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be included in | |
# all copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
# THE SOFTWARE. | |
# | |
use strict; | |
use warnings; | |
use Getopt::Long; | |
use Pod::Usage; | |
use WebService::Linode::DNS; | |
# File to store apikey. If undefined or blank, use ~/.linode-apikey. | |
# | |
my $apiKeyFile = ''; | |
# Default resource record templates. | |
# | |
my %mailTemplate = ( resourceid => 0, name => '', type => 'MX' ); | |
my %xmppTemplate = ( resourceid => 0, name => '_xmpp-server', protocol => '_tcp', type => 'SRV', weight => 0, port => 5269 ); | |
my %jabberTemplate = ( resourceid => 0, name => '_jabber', protocol => '_tcp', type => 'SRV', weight => 0, port => 5269 ); | |
my %ghsTemplate = ( resourceid => 0, type => 'CNAME', target => 'ghs.google.com' ); | |
# Google Apps DNS Records | |
# | |
my @googleMailRR = ( | |
{ %mailTemplate, target => 'aspmx.l.google.com', priority => 10 }, | |
{ %mailTemplate, target => 'alt1.aspmx.l.google.com', priority => 20 }, | |
{ %mailTemplate, target => 'alt2.aspmx.l.google.com', priority => 20 }, | |
{ %mailTemplate, target => 'aspmx2.googlemail.com', priority => 30 }, | |
{ %mailTemplate, target => 'aspmx3.googlemail.com', priority => 30 }, | |
{ %mailTemplate, target => 'aspmx4.googlemail.com', priority => 30 }, | |
{ %mailTemplate, target => 'aspmx5.googlemail.com', priority => 30 }, | |
{ %mailTemplate, type => 'TXT', target => 'v=spf1 a mx include:aspmx.googlemail.com -all' }, | |
); | |
my @googleXMPPJabberRR = ( | |
{ %xmppTemplate, target => 'xmpp-server.l.google.com', priority => 5 }, | |
{ %xmppTemplate, target => 'xmpp-server1.l.google.com', priority => 20 }, | |
{ %xmppTemplate, target => 'xmpp-server2.l.google.com', priority => 20 }, | |
{ %xmppTemplate, target => 'xmpp-server3.l.google.com', priority => 20 }, | |
{ %xmppTemplate, target => 'xmpp-server4.l.google.com', priority => 20 }, | |
{ %jabberTemplate, target => 'xmpp-server.l.google.com', priority => 5 }, | |
{ %jabberTemplate, target => 'xmpp-server1.l.google.com', priority => 20 }, | |
{ %jabberTemplate, target => 'xmpp-server2.l.google.com', priority => 20 }, | |
{ %jabberTemplate, target => 'xmpp-server3.l.google.com', priority => 20 }, | |
{ %jabberTemplate, target => 'xmpp-server4.l.google.com', priority => 20 }, | |
); | |
my @googleGHSRR = ( | |
{ %ghsTemplate, name => 'calendar' }, | |
{ %ghsTemplate, name => 'docs' }, | |
{ %ghsTemplate, name => 'mail' }, | |
{ %ghsTemplate, name => 'sites' }, | |
{ %ghsTemplate, name => 'start' }, | |
); | |
# ============================================================================= | |
# Do not change anything below this line. | |
# ============================================================================= | |
# | |
die "This script needs to be run interactively." if (! -t STDIN); | |
# Handle options. | |
# | |
my ($chat, $debug, $domainName, $force, $ghs, $help, $mail); | |
my $result = GetOptions( | |
'd=s' => \$domainName, | |
'c' => \$chat, | |
'f' => \$force, | |
'g' => \$ghs, | |
'm' => \$mail, | |
'v' => \$debug, | |
'help|h|?' => \$help | |
); | |
# Usage | |
# | |
pod2usage(1) if $help; | |
pod2usage(1) if ! $domainName; | |
pod2usage(1) if (! $chat) && (! $ghs) && (! $mail); | |
# Prompt to see if we should delete conflicting records or just add the new Google records. | |
# | |
if (! defined($force)) { | |
$force = parseresp(prompt("Would you like to delete any conflicting dns records? [Y/n] ")); | |
} | |
# Get API key and create api object. | |
# | |
my $apiKey = getApiKey($apiKeyFile); | |
my $api = new WebService::Linode::DNS( apikey => $apiKey ); | |
# Get domain object. | |
# | |
my $domain = $api->domainGet( domain => $domainName ) || | |
die "ERROR: Domain not found, please create the initial records first.\n"; | |
# XMPP+Jabber Records | |
# | |
processRRs($api, $domain, \@googleXMPPJabberRR, $force) if $chat; | |
# Mail Records | |
# | |
processRRs($api, $domain, \@googleMailRR, $force) if $mail; | |
# GHS Records | |
# | |
processRRs($api, $domain, \@googleGHSRR, $force) if $ghs; | |
# Save the domain. | |
# | |
$api->domainSave(%$domain) || die "Couldn't save $domainName\n"; | |
# All done. | |
# | |
exit(0); | |
# Subroutines | |
# | |
sub processRRs { | |
my $api = shift; | |
my $domain = shift; | |
my $resourceRecords = shift; | |
my $force = shift; | |
# Remove any existing records. | |
# | |
if ($force) { | |
for my $nRecord (@$resourceRecords) { | |
for my $eRecord (domainGetRRs($api, $domain->{domainid}, $nRecord->{type})) { | |
if (($eRecord->{type} =~ m/mx/i) && ($eRecord->{name} eq "")) { | |
deleteRR($api, $eRecord); | |
} elsif (($eRecord->{type} =~ m/txt/i) && ($eRecord->{target} =~ m/v=spf/i)) { | |
deleteRR($api, $eRecord); | |
} elsif (($eRecord->{type} =~ m/srv/i) && ($eRecord->{name} =~ m/_xmpp-server/i)) { | |
deleteRR($api, $eRecord); | |
} elsif (($eRecord->{type} =~ m/srv/i) && ($eRecord->{name} =~ m/_jabber/i)) { | |
deleteRR($api, $eRecord); | |
} elsif (($eRecord->{type} =~ m/cname/i) && ($eRecord->{target} =~ m/ghs.google.com/i)) { | |
deleteRR($api, $eRecord); | |
} | |
} | |
} | |
} | |
# Create new records. | |
# | |
for my $record (@$resourceRecords) { | |
debug("SAVING RR: TYPE=$record->{type} NAME=$record->{name} TARGET=$record->{target}"); | |
my $rr = $api->domainResourceSave( 'domainid' => $domain->{domainid}, %$record ) || | |
die "Could not save TYPE=$record->{type} NAME=$record->{name} TARGET=$record->{target}\n"; | |
} | |
} | |
sub deleteRR { | |
my $api = shift; | |
my $record = shift; | |
debug("DELETING RR: TYPE=$record->{type} NAME=$record->{name} TARGET=$record->{target}"); | |
my $result = $api->domainResourceDelete( resourceid => $record->{resourceid} ) || | |
warn "WARNING: Could not delete TYPE=$record->{type} NAME=$record->{name} TARGET=$record->{target}\n"; | |
return $result; | |
} | |
sub domainGetRRs { | |
my $api = shift; | |
my $domainId = shift; | |
my $domainRRType = shift; | |
my @domainRRs = (); | |
my $rrs = $api->domainResourceList( domainid => $domainId ) || | |
die "ERROR: Could not retrieve domain resource list.\n"; | |
for my $rr (@$rrs) { | |
push(@domainRRs, $rr) if ($rr->{type} =~ m/^$domainRRType$/i); | |
} | |
return @domainRRs; | |
} | |
sub getApiKey { | |
my $apiKeyFile = shift; | |
my $apiKey; | |
if (!length($apiKeyFile)) { | |
$apiKeyFile = (getpwnam(getlogin()))[7] . '/.linode-apikey'; | |
} | |
if (-f $apiKeyFile) { | |
chomp ($apiKey = `cat $apiKeyFile`); | |
} else { | |
$apiKey = prompt("Please enter your Linode API Key: "); | |
system "echo '$apiKey' > $apiKeyFile"; | |
} | |
return $apiKey; | |
} | |
sub parseresp { | |
my $response = shift; | |
my $val = 0; | |
chomp($response); | |
$val = 1 if ($response =~ m/^y/i ); | |
$val = 1 if ($response eq ""); | |
return $val; | |
} | |
sub prompt { | |
my $promptstring = shift; | |
print $promptstring; | |
chomp (my $retstring = ''); | |
return $retstring; | |
} | |
sub debug { | |
my $msg = shift; | |
print STDERR $msg, "\n" if $debug; | |
} | |
__END__ | |
=head1 NAME | |
googleapps-dns.pl - Create Google Apps DNS Records in Linode DNS Manager | |
=head1 SYNOPSIS | |
googleapps-dns.pl [ -d domainname ] [ -m ] [ -c ] [ -f ] [ -v ] [ -h ] | |
=head1 OPTIONS | |
-d domainname | |
Specify the domain name for adding the records. This field is | |
required. | |
-c Add Google Chat's Jabber and XMPP records to route external | |
chat program to Google's services. | |
-g Add CNAMES that point calendar.domainname, docs.domainname, | |
mail.domainname, sites.domainname, and start.domainname to | |
ghs.google.com. | |
-m Add MX and SPF records for routing mail to Google Apps. | |
-f Force deletion of any conflicting records. | |
-v Enable verbose debugging messages. | |
-h Display help and options. | |
=head1 DESCRIPTION | |
B provides a wizard to populate DNS records in the Linode | |
DNS manager for Google Apps. It requires that the domain already exist. It | |
would create the standard DNS entries which can be pruned manually later. | |
=cut |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment