Introducing Karman

Posted by David Estes on Mar 10, 2014

Ever wanted to write a webapp that took advantage of cloud storage? Or a plugin for that matter? A common issue that can crop up with writing apps like this is that the app can become easily tied down to a specific cloud provider (i.e. Amazin S3, Rackspace CDN, or Google Cloud). Introducing Kármán: A standardized, multi-provider, easy-to-use, Grails based storage interface.

Karman makes dealing with cloud files a cake walk. By taking advantage of Groovy magic, this interface can provide both super simple storage interfaces as well as more advanced interfaces. Uploading a file to a karman provider can be done in just a few lines:

def provider = StorageProvider.create(provider: 's3', accessKey: 'xxx', secretKey: 'xxx')
provider['mybucket']['sample.txt'] = "Storing data into s3 is a breeze."
//or
provider['mybucket']['sample.txt'] = new File('/path/to/sample.txt')

//or 
def file = provider['mybucket']['sample.txt']
file.bytes = byteArray
file.save('public-read')

Thats seems almost too easy to be true doesn't it? Not only can you assign values from local files or local data, but it also becomes super convenient to transfer data from bucket to bucket or even across different CDN platforms:

def s3 = StorageProvider.create(provider: 's3', accessKey: 'xxx', secretKey: 'xxx')
def rackspace = StorageProvider.create(provider: 'rackspace', accessKey: 'xxx', secretKey: 'xxx')

s3['mybucket']['demo.pdf'] = rackspace['mycontainer']['demo.pdf']

The StorageProvider

The storage provider is where our journey begins. It is the core interface from which your application interacts. Within each karman add-on exists an implimentation of a StorageProvider. While you can create instances of these specific providers individually, it ties down your app to that provider. To get around this Karman adopts the principal of Factories! In the standard com.bertramlans.plugins.karman.StorageProvider class exists a bunch of minions capable of creating your cloud specific provider without coupling your code. This can be done by registering provider types. An example of how to instantiate an S3 provider using the factory can be seen below:

import com.bertramlabs.plugins.karman.StorageProvider

def s3        = StorageProvider.create(provider: 's3', accessKey: 'xxx', secretKey: 'xxx')
def rackspace = StorageProvider.create(provider: 'rackspace', accessKey: 'xxx', secretKey: 'xxx')
def local     = StorageProvider.create(provider: 'local', basePath: '/local/fs/path')

Pretty simple right? With this common interface, your app or plugin can easily be extended to work with whatever providers karman has implemented!

Local Storage

Another base feature of karman is the local storage provider. This comes standard with Karman and provides an identical interface to local files that one might have in the cloud. This can make things super easy to synchronize files from your local storage into the cloud ( see the grails-cdn-asset-pipeline plugin):

def s3 = StorageProvider.create(provider: 's3', accessKey: 'xxx', secretKey: 'xxx')
def local = StorageProvider.create(provider: 'local', basePath: '/path/to/local')

s3['mybucket']['demo.pdf'] = local['documents']['demo.pdf']

On top of this karman provides a grails url mapping for serving the files you place in a local store. All of this is configurable, of course, but now you have a great way to standardize user uploads. Keep them in a local store as you build out your product, then move them to the cloud with just a few configuration changes!

Progress!

At the time of this article, only S3 and Local storage is available. Work is also currently being done to provide Rackspace CDN and Google Cloud support. Have a CDN you want to use? Extending Karman is easy! Take a look at the docs for more information.

Eventually, Karman will support more than just cloud storage. It will provide standard interfaces for managing an assortment of cloud services!