Google Cloud DNS – Java SDK sample

So, you want to use Google Cloud DNS? It’s not as polished as Amazon’s Route 53 service, to the point where the UI doesn’t display your entries, nor allow you to edit them. The command line tool even fires up an editor for you to modify some JSON to make any changes to the records. But if you’re determined, then here’s some help.


You’re going to need a JSON file describing your entries:-

{
   "additions":[
      {
         "kind":"dns#resourceRecordSet",
         "name":"example.com.",
         "rrdatas":[
            "93.184.216.119"
         ],
         "ttl":21600,
         "type":"A"
      },
      {
         "kind":"dns#resourceRecordSet",
         "name":"example.com.",
         "rrdatas":[
            "10 aspmx.l.google.com"
         ],
         "ttl":21600,
         "type":"MX"
      },
      {
         "kind":"dns#resourceRecordSet",
         "name":"www.example.com.",
         "rrdatas":[
            "example.com."
         ],
         "ttl":21600,
         "type":"CNAME"
      }
   ]
}

And you’ll need a Google Project, with the DNS API enabled. And then you’ll need an OAuth2 service account credentials (an email address and a p12 file).

Once you’ve got them, you can do this:-

private static final String emailAddress = "[email protected]";
private static final String p12file = "oauth2.p12";
private static final String googleProjectId = "google-project-123";
private static final String zoneId = "dns-examplecom";
private static final String zoneDescription = "DNS for example.com";
private static final String dnsDomain = "example.com.";
private static final String dnsZoneFile = "example.com.json";
 
public static void main(String[] args) {
        JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
        HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
 
        LOGGER.info(String.format("Getting access token for '%s'", emailAddress));
        GoogleCredential credential = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId(emailAddress)
                .setServiceAccountPrivateKeyFromP12File(new File(p12file))
                .setServiceAccountScopes(DnsScopes.all())
                .build();
        credential.refreshToken();
        String accessToken = credential.getAccessToken();
 
        Dns d = new Dns(httpTransport, JSON_FACTORY, credential);
 
        LOGGER.info(String.format("Searching for zone: %s", googleProjectId));
        boolean found = false;
        ManagedZonesListResponse mzlr = d.managedZones().list(googleProjectId).execute();
        for (ManagedZone singleZone : mzlr.getManagedZones()) {
            if (singleZone.getName().compareToIgnoreCase(zoneId) == 0) {
                found = true;
            }
        }
 
        if (found) {
            LOGGER.info("Zone exists - getting entries");
            List<ResourceRecordSet> deletions = new ArrayList<ResourceRecordSet>();
            ResourceRecordSetsListResponse rrslr = d.resourceRecordSets().list(googleProjectId, zoneId).execute();
            LOGGER.debug(rrslr.toPrettyString());
            for (ResourceRecordSet singleRrs : rrslr.getRrsets()) {
                // Leave out the SOA and NS, otherwise you can't delete the zone
                if (singleRrs.getType().compareToIgnoreCase("SOA") != 0 && singleRrs.getType().compareToIgnoreCase("NS") != 0) {
                    deletions.add(singleRrs);
                }
            }
 
            if (deletions.size() > 0) {
                LOGGER.info("Deleting existing entries in the zone");
                Change c = new Change();
                c.setDeletions(deletions);
                d.changes().create(googleProjectId, zoneId, c).execute();
            }
        } else {
            LOGGER.info(String.format("Creating zone '%s' for domain '%s'", zoneId, dnsDomain));
            ManagedZone mz = new ManagedZone()
                    .setDnsName(dnsDomain)
                    .setDescription(zoneDescription)
                    .setName(zoneId);
            d.managedZones().create(projectId, mz).execute();
        }
 
        LOGGER.info(String.format("Creating records from file '%s'", zoneDataFile));
        Change c = om.readValue(new File(zoneDataFile, Change.class);
        LOGGER.debug(d.changes().create(googleProjectId, zoneId, c).execute().toPrettyString());
 
        LOGGER.info(String.format("Getting nameservers for domain '%s'", dnsDomain);
        List<String> ns = d.managedZones().get(googleProjectId, zoneId).execute().getNameServers();
        for (String singleNs : ns) {
            LOGGER.info(singleNs);
        }
}

public static void main(String[] args) {
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();

LOGGER.info(String.format("Getting access token for ‘%s’", emailAddress));
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(emailAddress)
.setServiceAccountPrivateKeyFromP12File(new File(p12file))
.setServiceAccountScopes(DnsScopes.all())
.build();
credential.refreshToken();
String accessToken = credential.getAccessToken();

Dns d = new Dns(httpTransport, JSON_FACTORY, credential);

LOGGER.info(String.format("Searching for zone: %s", googleProjectId));
boolean found = false;
ManagedZonesListResponse mzlr = d.managedZones().list(googleProjectId).execute();
for (ManagedZone singleZone : mzlr.getManagedZones()) {
if (singleZone.getName().compareToIgnoreCase(zoneId) == 0) {
found = true;
}
}

if (found) {
LOGGER.info("Zone exists – getting entries");
List<ResourceRecordSet> deletions = new ArrayList<ResourceRecordSet>();
ResourceRecordSetsListResponse rrslr = d.resourceRecordSets().list(googleProjectId, zoneId).execute();
LOGGER.debug(rrslr.toPrettyString());
for (ResourceRecordSet singleRrs : rrslr.getRrsets()) {
// Leave out the SOA and NS, otherwise you can’t delete the zone
if (singleRrs.getType().compareToIgnoreCase("SOA") != 0 && singleRrs.getType().compareToIgnoreCase("NS") != 0) {
deletions.add(singleRrs);
}
}

if (deletions.size() > 0) {
LOGGER.info("Deleting existing entries in the zone");
Change c = new Change();
c.setDeletions(deletions);
d.changes().create(googleProjectId, zoneId, c).execute();
}
} else {
LOGGER.info(String.format("Creating zone ‘%s’ for domain ‘%s’", zoneId, dnsDomain));
ManagedZone mz = new ManagedZone()
.setDnsName(dnsDomain)
.setDescription(zoneDescription)
.setName(zoneId);
d.managedZones().create(projectId, mz).execute();
}

LOGGER.info(String.format("Creating records from file ‘%s’", zoneDataFile));
Change c = om.readValue(new File(zoneDataFile, Change.class);
LOGGER.debug(d.changes().create(googleProjectId, zoneId, c).execute().toPrettyString());

LOGGER.info(String.format("Getting nameservers for domain ‘%s’", dnsDomain);
List<String> ns = d.managedZones().get(googleProjectId, zoneId).execute().getNameServers();
for (String singleNs : ns) {
LOGGER.info(singleNs);
}
}

and your Maven dependencies are

<dependency>
   <groupId>com.google.apis</groupId>
   <artifactId>google-api-services-oauth2</artifactId>
   <version>v2-rev81-1.19.0</version>
</dependency>
<dependency>
   <groupId>com.google.apis</groupId>
   <artifactId>google-api-services-dns</artifactId>
   <version>v1beta1-rev12-1.19.0</version>
</dependency>
<dependency>
   <groupId>org.codehaus.jackson</groupId>
   <artifactId>jackson-mapper-asl</artifactId>
   <version>1.9.13</version>
</dependency>
<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-classic</artifactId>
   <version>1.1.2</version>
</dependency>

Sample code available in Git.

This is my personal blog - all views are my own.

Tagged with: , ,