Google Cloud DNS API example with ruby

Recently, I did my first steps with Google Cloud DNS API. I was using ruby to do my development and ruby library is in early-stage (May 2017) and has only alpha version.

It still works pretty well and I have been able to implement everything I needed.

However, I had some hard time to figure out how to do that. Despite there are lots of documentations in the beginning I was a bit confused. There are lots of articles about popular Google API, but not match about DNS and ruby.

So I decided to share my experience and put the whole process here in simple steps:

  1. Setup
  2. Authorization
  3. Create record
  4. Delete record
  5. Update existing record

1. Setup

Google provide ruby libriry via gem. To install it simply run:

gem install google-api-client

or set it with Gemfile. More information can be found on Google's github page:
https://github.com/google/google-api-ruby-client

Google API has three types of  authentication schemes:

  • API keys
  • Service accounts
  • User accounts


More information and implementation details can be found on Google docs page. Some examples also available on github page. Google Cloud DNS is a Platform API and (as it is mentioned on docs) to access this type of API we need to use "Service accounts".

First, lets enable DNS API. Go to API Manager Dashboard:



then click "Enable API" :



and select Google DNS API:



This will activate DNS API. Next step is to get credentials. To do this, got to "Credentials" page, where Google will prompt you to create new credentials:



You can select "Help me choose", answer couple questions and get to "Service account key" creation page or choose it right away. Then fill several page and click "Create":


After that, the page will prompt you to download your key. Note, that you can download it only now and once, so save it in the safe place. Note, that you need to select role "DNS Administrator" and JSON as key format.

Now we can start using this file in our ruby script.

We start with requiring Google libraries and including Google::Apis::DnsV1 module to reference directly its members.

require 'googleauth'
require 'google/apis/dns_v1'

include Google::Apis::DnsV1

2. Authorization

Google API client for ruby uses Google Auth library which is still alpha (as of May 2017). This auth library will get authentication data from the JSON file we have just downloaded. We need to let know the auth library where to find this file. This information must be stored in environment variable GOOGLE_APPLICATION_CREDENTIALS:

ENV['GOOGLE_APPLICATION_CREDENTIALS'] = "/path/to/my/service_auth_file.json"

scopes = [AUTH_CLOUD_PLATFORM,
          AUTH_CLOUD_PLATFORM_READ_ONLY,
          AUTH_NDEV_CLOUDDNS_READONLY,
          AUTH_NDEV_CLOUDDNS_READWRITE]
      
auth = Google::Auth.get_application_default(scopes)


The list of scopes already defined in DNS library file. And function "get_application_default" receives scopes and return authentication. We will assign it DNS service object:

dnsmgm = DnsService.new
dnsmgm.authorization = auth


3. Create record

Module DnsV1 implements 8 main classes:

  • Change
  • ListChangesResponse
  • ManagedZone
  • ListManagedZonesResponse
  • Project
  • Quota
  • ResourceRecordSet
  • ListResourceRecordSetsResponse

Those classes reflect the resource types described in DNS API documentation. Main class "DnsService" provides collection of methods that allows to DNS records/zones manipulation and return resource classes.

Zones are the top level domains and record types (A, CNAME, SRV etc.) can be managed by "Changes" class.

Lets say we have already created our zone "mytest.example.ca." within project with id "neat-tube-166212".

Zone name is "example-com".

Now, to create A record for zone "mytest.example.ca." that point to IP 123.111.222.10, the code would look like:

rrs = ResourceRecordSet.new(name: 'mytest.example.ca.',
                            type: 'A',
                            kind: "dns#resourceRecordSet",
                            ttl:  300,
                            rrdatas: ["123.111.222.10"])
body = Change.new
body.additions = [rrs]
dnsmgm.create_change 'neat-tube-166212', 'example-com', body




First we create ResourceRecordSet object and than use it in new Change class. Note member "additions" that supposed to contain array of ResourceRecordSet instances.

4. Delete record 

Before deleting the record, we need to find it and then create Change class with "deletions" member which contains the record. It can be done as following:

rrs = dnsmgm.list_resource_record_sets('neat-tube-166212',
             'example-com', name: 'mytest.example.ca.', type: 'A')

body = Change.new
body.deletions = rrs.rrsets
dnsmgm.create_change 'neat-tube-166212', 'example-com', body



5. Update existing record

There is no direct method to update existing record. At lease, I did not found one. So to update existing record it is simply delete / create record procedure as explained above. Create Change class instance, put old RRS to "deletions" and new to "additions".

And the whole example:

require 'googleauth'
require 'google/apis/dns_v1'

include Google::Apis::DnsV1

project_id = 'neat-tube-166212'
zone_name  = 'example-com'

ENV['GOOGLE_APPLICATION_CREDENTIALS'] = "my-project.json"

scopes = [AUTH_CLOUD_PLATFORM,
          AUTH_CLOUD_PLATFORM_READ_ONLY,
          AUTH_NDEV_CLOUDDNS_READONLY,
          AUTH_NDEV_CLOUDDNS_READWRITE]

auth = Google::Auth.get_application_default(scopes)

dnsmgm = DnsService.new
dnsmgm.authorization = auth

# create record
rrs = ResourceRecordSet.new(name: 'mytest.example.ca.',
                            type: 'A',
                            kind: "dns#resourceRecordSet",
                            ttl:  300,
                            rrdatas: ["123.111.222.10"])
body = Change.new
body.additions = [rrs]
dnsmgm.create_change project_id, zone_name, body

# delete record
rrs = dnsmgm.list_resource_record_sets(project_id, zone_name,
                                       name: 'mytest.example.ca.', type: 'A')

body = Change.new
body.deletions = rrs.rrsets
dnsmgm.create_change project_id, zone_name, body




Comments

Popular posts from this blog

Asterisk Queues Realtime Dashboard with amiws and Vue

YAML documents parsing with libyaml in C