Deltacloud sings a new tune

04 March 2010

A few weeks ago, I came across Sinatra, a minimalist Ruby web framework, much leaner, meaner and simpler than Rails — while it’s probably not a good fit for traditional database-backed web applications, it seemed like an ideal framework for Deltacloud Core.

Deltacloud Core is a cross-cloud API providing abstraction and compatibility across multiple clouds. There are quite a few such API’s out there; what makes Deltacloud unique is that it is not a client-side library tied to a specific language. Instead, it is a RESTful web service, initially written in Rails by Bob McWhirter.

While Rails was a good initial framework for Detlacloud Core, and is the default Ruby web framework for a reason, there’s a few things that make it overkill for a simple webservice:

  • Deltacloud Core is stateless, and therefore has no need to store anything in a database; that means we’ll never use Rails’ ActiveRecord
  • Deltacloud Core isn’t really a MVC app; it’s simply an adapter around existing API’s, and the split of responsibility that MVC implies doesn’t really fit with how an API adapter works.
  • Deltacloud Core hooks into a few places in the handling of requests, most importantly to do parameter validation based on the operation being performed in the API. Much easier to do with a simple framework like Sinatra

Of course, the biggest draw of Sinatra is that it concentrates all the controller code in one place (currently ~ 300 lines in server.rb), which makes it much easier to understand how the whole application is put together. More generally, using Sinatra makes it possible to concentrate code in fewer files, increasing readability.

Sinatra Additions

Out of the box, Sinatra fell short of our needs in two areas: RESTful request validation and responding with a variety of content types.

Michal and I took care of request validation with a small custom DSL for describing RESTful operations, cleverly called Rabbit. That DSL lets us talk about collections and operations on collections, and generates validation logic and online documentation on-the-fly. You can browse an instance of Deltacloud Core and immediately see what operations are available, and what parameters a specific operation like create instance accepts. (Why and how that is important is a topic for another blog post)

Deltacloud Core can be used in two ways: you can either point your web browser at it and browse a variety of information about your objects in a specific cloud, or make RESTful requests that return XML responses. That dual nature makes it necessary to respond to some requests with HTML, and to others with XML. Sinatra doesn’t have a mechanism that’s as convenient as Rails’ respond_to for this, though there’s a nice extension that does exactly that, so that we could write listing of a collection, any collection, (model in the code below), simply as

singular = model.to_s.singularize.to_sym
@elements = driver.send(model.to_sym, credentials, filter)
instance_variable_set(:"@#{model}", @elements)
respond_to do |format|
  format.xml  { return convert_to_xml(singular, @elements) }
  format.html { haml :"#{model}/index" }

The Sinatra respond_to extension actually didn’t do content negotiation based on the Accept header; we added that based on a couple of existing Rack extensions. And discovered in the process that Chrome’s Accept header is utterly insane.

All in all, the move to Sinatra worked out very well; existing functionality was easy to preserve, and we added validation and self-documentation to Deltacloud Core, both in human-readable format and as (experimental) XML. Next up: more features for the API.

Creative Commons License Watzmann.Blog by David Lutterkort is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.

Generated with Jekyll