The GitHub platform is a force in the world of open source. There are millions of open source projects on GitHub, across a wide range of topics and programming languages. We even have a bunch of our open source projects on there as well in the DNSimple organization, such as the domain management API clients, various add-ons for our new domain management platform like the Heroku add-on, our newly updated chef cookbook, and so many others.

In addition to maintaining our own open source projects on GitHub, we also contribute to other projects that matter to us. Recently I submitted a pull request to the dnscontrol project. This is a bit about the steps I took to get my contribution ready and published in just a few days.

The dnscontrol project

Back in January, Mark Henderson from StackExchange wrote about how they decided which DNS providers to use for the StackExchange network. In that post Mark mentioned a tool they wrote to manage synchronizing data between different DNS providers, indicating they would open source that tool in March.

Fast forward to March 14th and the announcement of the dnscontrol project.

FWIW, dnscontrol is not the only project for managing DNS at multiple providers. Shopify also has an open source project called Record Store that manages DNS using a git-based workflow. They have providers for DNSimple and Dyn. Take a look for a different approach to managing DNS accross multiple providers.

Back to the dnscontrol project. Shortly after it was announced I decided I wanted to write a provider for DNSimple.

Fork and clone

The first thing I did was fork and clone the project. Since this project is a Go project, it's easiest to put it in the $GOPATH directly. Thus, I cloned my fork into $GOPATH/src/ (I later moved the project over into the dnsimple organization, which is where the fork lives now). Once I had the project cloned, I started looking through the documentation and the code. Most young open source projects, even those that have existed for a long time as internal tools or libraries, have pretty limited documentation. There is some documentation for dnscontrol, but there isn't much on writing a new provider:

Writing a new DNS provider is a relatively straightforward process. You essentially need to implement the providers.DNSServiceProvider interface.

More info to follow soon.

Pretty limited, but that's ok, there's always the code!

Diving in

To understand how to write a provider, I began by looking at other providers. First I looked into the Gandi provider and the Cloudflare provider. These two providers are implemented differently, but they give a fairly good idea that I would need to implement GetNameservers and GetDomainCorrections. Initially I was under the impression that GetNameservers should return the current nameservers used for a domain, and my first commit demonstrates this lack of understanding. Fortunately, by opening the PR quickly, I found out what it was actually supposed to be.

One thing that made my job quite easy is that we already have a Go library for the DNSimple API v2. Having a solid library that is ready to go likely shaved hours off the time I would have spent to implement a provider had the library not been present.

Submitting the PR

My goal when I first started the provider was to get a fairly clear PR ready to go as fast as possible. I began work before getting on a flight from Copenhagen to Brussels, and managed to finish quite a bit of it while in the air. I spent 30 more minutes in my layover and got the code to the point where it was compiling. At this point I pushed up my repo and shared with the team.

I wrote up a little bit of documentation, added the provider to the list, and pushed the first commit. A few clean up commits later and I decided it was time to start testing against our sandbox. The way dnscontrol works is by using a little bit of JavaScript as the script as the configuration mechanism. Here's the JavaScript I used:

// define our registrar and providers
var dnsimple_reg = NewRegistrar("dnsimple", "DNSIMPLE");
var dnsimple = NewDnsProvider("dnsimple", "DNSIMPLE");

D("", dnsimple_reg, DnsProvider(dnsimple),
  A("@", ""),
  A("test", ""),
  AAAA("@", "2001:db8:85a3::8a2e:370:7334"),
  TXT("@", "This is a text record")

Initially I only started with the A record. Once that was functioning correctly, I added additional records.

Finally I performed a bit of additional clean up and submitted the PR!

Getting feedback

It is exceptional when you get immediate feedback on a pull request, and the project contributors acted quickly (which is awesome!)

After vendoring the dnsimple API client (and learning a bit about govendor), and making a few tweaks suggested by the project maintainer, I was essentially done. Another sign of an awesome maintainer is when they will actually make amendments to your PR to make it better. In this case, captncraig made some changes to allow the tests to run successfully against the DNSimple provider, and I didn't have to do a thing, which is pretty damn cool. Only 3 days after starting the provider implementation and pushin the PR, it was accepted into master.

Now what?

Having a PR accepted is cool, but eventually projects will evolve. If you contribute to a project, you may need to come back and update your contributions in the future. This is not something to be taken lightly, both from the contributor's perspective, as well as the maintainer's prospective. All code is legacy code and has to be maintained, so as a contributor it's important to be ready to jump back in at a later date if necessary.

Why contribute?

There are a number of reasons to contribute to projects. Here are a few of my personal reasons:

  • I enjoy writing software and contributing to other projects is a useful way to keep my skills sharp.
  • With each contribution you earn a bit of gratitude from the project author(s) and the open source community as a whole.
  • In certain cases contributions can represent a useful bit of engineering as marketing.
  • It just feels good to ship.

Whatever your reasons are, now is as good a time as any to through your hat into the ring and help out an open source project that is interesting to you. And remember that software is written by people (for the moment) and people should be treated with kindness and respect, so be nice to maintainers, be nice to contributors, and go out and make awesome software.