Experimental Resolution of Gem Dependencies with DNS


This week Jeremy Hinegardner (aka @copiousfreetime) was in Montpellier to visit. In addition to enjoying some good meals, good wine and time in the pool we also took this opportunity to work on an experimental gem dependency resolution system using DNS. I’ve written about this before and the latest gist has some new details in it as the result of our work this week.

First of all we’ve outlined how to deal with some of the dependency issues we had not yet dealt with, such as less-than, less-than-or-equals-to and not-equals. Additionally we outlined how to deal with situations where a dependency defines 2 or more requirements (such as ["> 1.0.0", "<= 2.0.0"]). We’ve also added in support for listing all known versions of a specific gem by moving the notion of the latest gem version so it uses a prefix of latest and then putting one PTR for each version of the gem on the gem domain name.

In addition to working on the details of the spec we also got some data loaded! Thanks to the work Jeremy did previously on his Gemology project a lot of the code had already been written. I spent some time working on moving the code we needed into the rubygems-dns project while Jeremy worked on exporting the existing specs we needed from his database and writing an import script. While the implementation is far from complete I’m happy to say that you can actually query the DNS server now and answer questions with it.

First a query to list all of the versions of a gem. We’ll use the Sinatra gem as an example:


dig @ns8.dnsimple.com sinatra.index.rubygems.org PTR

The result will be an unordered list of PTR records, with each record representing a version with the version number in reverse order:


sinatra.index.rubygems.org. 86400 IN PTR 1.3.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 0.1.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 5.1.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 6.1.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 7.1.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 0.2.0.sinatra.index.rubygems.org.
...snip...

So the first line indicates that there was a 0.3.1 version of Sinatra and line 2 indicates there was a 0.1.0 version of Sinatra.

Next, let’s get the latest version:


dig @ns8.dnsimple.com latest.sinatra.index.rubygems.org CNAME


latest.sinatra.index.rubygems.org. 600 IN CNAME e.0.3.1.sinatra.index.rubygems.org.

This shows us that 1.3.0.e is the latest sinatra version published (as of the snapshot).

Next, we can query for PTR records for that same name:


dig @ns8.dnsimple.com latest.sinatra.index.rubygems.org PTR


latest.sinatra.index.rubygems.org. 600 IN CNAME e.0.3.1.sinatra.index.rubygems.org.
e.0.3.1.sinatra.index.rubygems.org. 86400 IN PTR 1.tilt.index.rubygems.org.
e.0.3.1.sinatra.index.rubygems.org. 86400 IN PTR 1.rack.index.rubygems.org.

This shows us that the version 1.3.0.e has two runtime dependencies, tilt and rack, and that they require the latest version of the 1.x releases for each of those. We can then use:


dig @ns8.dnsimple.com 1.tilt.index.rubygems.org PTR

To show us that the latest version:


1.tilt.index.rubygems.org. 600 IN CNAME 2.3.1.tilt.index.rubygems.org

That’s it for now. There is more work to do, like encoding the <, <=, != and dependencies with 2 or more requirements, but this will at least give an example how this all might actually work.

, ,

  1. #1 by Carl Youngblood on September 19, 2011 - 4:31 am

    Sweet Anthony! Thanks for posting this update. I just decided to do a Google search and see if you had made any progress on this after you talked about it at a few RubyConfs. Glad to see you guys are working on it. Seems like a brilliant idea.

(will not be published)