Create the tools that you need
Domain Management Automation might sound like a big intimidating string of words, but actually it just means that you can solve the problems that are of importance to you. No matter how big or small they are.
I recently needed to automate some validation for my domains. I was creating a few CNAME records, and I wanted to know if they were available and ready for me to browse. My local Internet provider always plays tricks on me, so I either need to jump on my 3G/4G connection, or use a VPN to see if my new subdomain is available and ready to use. But last week I said enough! I wanted something I could run from my computer's terminal and see if my new records were available.
Basically, I want to type check test.example.com
and either get a Ready!
or Not yet available
response.
Since I work at DNSimple, I have access to internal APIs that I could also use to take this tool even further. This example demonstrates that even without that, it's possible to develop useful tools that combine the DNSimple domain API with other third-party APIs to solve problems quickly.
So I created a small ruby script that uses the DNSimple API and the Google Resolver API. The first thing I did was to understand how to use the Google API. With HTTParty, it was a trivial call.
url = "https://dns.google.com/resolve?name=#{query}&type=ANY"
json = HTTParty.get(url, verify: false) # Skips SSL Certificate validation with `verify: false`
response = JSON.parse(json)
I am using ANY
as the DNS record type to start with, but I could have settled down for CNAME
since all my records that needed validation are CNAME
records. #{query}
is a variable that I am passing to the ruby script from the command line.
Here is an example of a response from a Google Public DNS API call:
{
"Status": 0,
"TC": false,
"RD": true,
"RA": true,
"AD": false,
"CD": false,
"Question": [
{
"name": "test.example.com.",
"type": 255
}
],
"Answer": [
{
"name": "test.example.com.",
"type": 5,
"TTL": 86399,
"data": "test.example.com.s3-website-eu-west-1.amazonaws.com."
}
],
"Comment": "Response from 162.159.25.4"
}
Once I understood how to use Google's API, how to read the answer, and extract what I needed; I used the DNSimple API to see if the content of my DNS record matches the answer from Google.
dnsimple.zones.list_records(account.id, domain).data.each do |record|
if record.name == subdomain
check_with_google(record, query)
end
end
I retrieve the zone records for the domain in DNSimple and check the content of the record with Google:
def check_with_google(record, query)
if record.content == ask_google(query)
puts "✔️ Ready"
else
puts "❌ Not yet available"
end
end
The method ask_google
encapsulates the logic that I first discovered with HTTParty. In 50 lines, I have a quick way to verify my CNAME
records. It will definitely need some love to support other type of records and improve error handling if something goes wrong, but here is the full script:
#!/usr/bin/env ruby
require "dnsimple"
require "httparty"
require "json"
query = ARGV.last
# You can get a dnsimple access token following this guide: https://support.dnsimple.com/articles/api-access-token/
dnsimple = Dnsimple::Client.new(access_token: "xxx")
# Finds your current dnsimple account
account = dnsimple.identity.whoami.data.account
# Finds the record in dnsimple and asks google if they match
def check(dnsimple, query, account)
domain, subdomain = extract_domain(query)
dnsimple.zones.list_records(account.id, domain).data.each do |record|
if record.name == subdomain
check_with_google(record, query)
end
end
end
def check_with_google(record, query)
if record.content == ask_google(query)
puts "✔️ Ready"
else
puts "❌ Not yet available"
end
end
def ask_google(query)
url = "https://dns.google.com/resolve?name=#{query}&type=ANY"
json = HTTParty.get(url, verify: false)
response = JSON.parse(json)
# Google adds an extra "." at the end. We remove it.
response["Answer"].first["data"].chomp(".")
rescue NoMethodError
"not-found-on-google-yet"
end
def extract_domain(query)
arguments = query.split(".")
domain = arguments.slice(-2..-1).join(".")
subdomain = arguments[0..arguments.size - 3].join(".")
return domain, subdomain
end
check(dnsimple, query, account)
Conclusion
No matter how trivial a small script like this one looks, it greatly improved my workflow and removed guesswork and frustrations. My local ISP likes to hold on to old caches too often, and this little script helps me work around that. It's a tiny but powerful cog that can be plugged into a bigger script if needed.
Sebastian Hermida
Appreciates the finest things in life: clean code, good illustrations and carrot juice. Someday he will run a marathon.
We think domain management should be easy.
That's why we continue building DNSimple.
4.3 out of 5 stars.
Based on Trustpilot.com and G2.com reviews.