code-small.jpg

Cake Team Blogs

Haskell & Happstack on CloudFoundry

Posted by Anirvan Chakraborty

25/11/11 18:21

For the past few weeks I have been running some experiments on Cloud Foundry. I was hoping to combine my understanding of the internal workings of VMWare's Cloud Application Platform (vcap) with my Haskell code.

So, to make sure that we can run Haskell "in the cloud" (especially considering Julian Porter's CloudHaskell work), I decided to include the Haskell runtime and Happstack framework in Cloud Foundry.

Success!

And guess, what? It worked!

Before I tell you all the details and point you to my Github fork of vcap, I'll show you, starting with Figure 1, which shows that vmc runtimes now includes [The Glorious Glasgow--ridiculous, I know!] Haskell compiler.

Figure 1. GHC runtime

runtimes

Next, I have the Happstack framework; Figure 2 shows the output of running vmc frameworks.

Figure 2. Happstack framework

frameworks

Moving on, I'm going to deploy trivial Haskell/Happstack application. (Naturally, I could write some amazing Haskell code, but Hello World is the most didactical!). The source is

module Main where

import Happstack.Server (nullConf, simpleHTTP, toResponse, ok)

main :: IO ()
main = simpleHTTP nullConf $ ok "Hello, World! Haskell is COOL!"

Now that I have the application, let's deploy it in CloudFoundry, using the usual vmc push command. The updated vmc recognises that the app is indeed a Haskell/Happstack one and selects the appropriate runtime/framework combination. (Viz Figure 3).

Figure 3. vmc push

push

Finally, we need to show you that the application is indeed running. So, on to the browser and go to http://haskellapp.vcap.me and see Figure 4.

Figure 4. The result

proof

The code

Let's take a look at what we had to do to get it running.

Hacking vcap

To make sure that the Cloud Controller understands the new runtime and framework, I modified the 'app' model by adding the following code:

Runtimes = %w[ruby18 ruby19 java node php erlangR14B02 python26 haskell]
Frameworks = %w[sinatra rails3 java_web spring grails node php otp_rebar lift wsgi django happstack unknown]
...
...
when "happstack/1.0"
    self.framework = 'happstack'
    self.runtime   = 'haskell'
end

Next up is the cloud_controller.yml file

  haskell:
    version: "[6-7].*"

Now we need make sure that the 'dea' is configured, so the dea.yml file

  haskell:
    executable: /usr/bin/runhaskell
    version: 6.12.1
    version_flag: '--version'
    environment:

So far the cloud controller knows about the runtime and framework and the dea is configured to deal with them as well. Now we need make sure that a Haskell/Happstack app can be staged in cloud foundry. We added the HappstackPlugin and the manifest for Happstack.

class HappstackPlugin < StagingPlugin
  def framework
    'happstack'
  end

  def stage_application
    Dir.chdir(destination_directory) do
      create_app_directories
      copy_source_files
      create_startup_script
    end
  end

  def start_command
    "runhaskell Main.hs"  #Equivalent of
  end

  ...
end
---
name: "happstack"
runtimes:
  - haskell:
      version: '6.12.1'
      description: 'The Glorious Glasgow Haskell Compilation System'
      executable: /var/vcap/runtimes/haskell-6.12.1/bin/runhaskell
      default: true
app_servers:
detection:
  - "*.hs": true
staged_services:

In this post, I'm ignoring the pains of installing Haskell/Happstack on Ubuntu 10.04--there's a long blog post coming up about that soon! For the brave, take a look at setup/vcap_setup in the vcap repository.

Hacking vmc

Not a lot but still you would need the following to get vmc to understand the new runtime and framework: frameworks.rb

module VMC::Cli

  class Framework

    DEFAULT_FRAMEWORK = "http://b20nine.com/unknown"
    DEFAULT_MEM = '256M'

    FRAMEWORKS = {
      ...,
      'Happstack'         =&gt; ['happstack',
         { :mem =&gt; '128M', :description =&gt; 'Happstack Web Application'}]
    }

    class &lt;&lt; self

      def known_frameworks
        FRAMEWORKS.keys
      end

      def lookup(name)
        return Framework.new(*FRAMEWORKS[name])
      end

      def detect(path)
        Dir.chdir(path) do
          ...
          ...
          # Happstack
          elsif !Dir.glob('*.hs').empty?
            return Framework.lookup('Happstack')

          end
        end
        nil
      end

    end

...
end

References & Downloads

We'll send a pull request to the VMWare guys soon (after a bit of gold platting...), but in the meantime, you can fork https://github.com/anirvanc/vcap and https://github.com/anirvanc/vmc and get hacking!

Topics: Haskell

Subscribe to Email Updates