Opa

The Opa service lets you build and run applications written in the Opa language very easily. Opa is a concise and elegant language for writing distributed web applications

Here is what a Chat application looks like when written using Opa:

do Resource.register_external_css("http://twitter.github.com/bootstrap/assets/css/bootstrap-1.1.1.min.css") do Resource.register_external_css("http://chat.opalang.org/resources/css.css") type message = {author: string /**The name of the author (arbitrary string)*/ ; text: string /**Content entered by the user*/} @publish room = Network.cloud("room"): Network.network(message) user_update(x: message) = line = <div class="row line"> <div class="span1 columns userpic" /> <div class="span2 columns user">{x.author}:</div> <div class="span13 columns message">{x.text} </div> </div> ignore(Dom.put_at_start(#conversation, Dom.of_xhtml(line))) broadcast(author) = text = Dom.get_value(#entry) message = {~author ~text} do Network.broadcast(message, room) Dom.clear_value(#entry) start() = author = Random.string(8) <div class="topbar"><div class="fill"><div class="container"><div id=#logo/></div></div></div> <div id=#conversation class="container" onready={_ -> Network.add_callback(user_update, room)}> </div> <div id=#footer><div class="container"> <input id=#entry class="xlarge" onnewline={_ -> broadcast(author)}/> <div class="btn primary" onclick={_ -> broadcast(author)}>Post</div> </div></div> server = Server.one_page_server("Chat", -> start())

Basic Use

Let’s assume that you are building a DotCloud application called “ramen”. For the sake of simplicity, we will also assume that everything related to this application is located in a directory called “ramen-on-dotcloud”.

Let’s setup our environment:

$ dotcloud create ramen
Created application "ramen"
$ mkdir ramen-on-dotcloud

A DotCloud application is described by a Build Files, which is a simple YAML file named “dotcloud.yml” located in our “ramen-on-dotcloud” directory. To add a new service to our app, we just add the following lines to “ramen-on-dotcloud/dotcloud.yml”:

www:
  type: opa

Our Opa code will live side by side with this Build File. Let’s write a minimal Opa application; create the file “ramen-on-dotcloud/main.opa” with the following content:

server = Server.one_page_server("Hello", ( -> <>Hello World!</>))

To automatically build the application we will use a Makefile, edit the file “ramen-on-dotcloud/Makefile” and write:

NAME = hello.exe

SRC  = main.opa

all: $(NAME)

$(NAME):
     opa $(SRC)

clean:
     rm -f $(NAME)
     rm -rf _build

Warning

A Makefile must be indented with tabulations, not spaces.

Before you push your application on DotCloud, let’s make sure that everything is in place:

ramen-on-dotcloud/   # Your application directory
├── dotcloud.yml     # The DotCloud stack description
├── main.opa         # The Opa source code
└── Makefile         # Let you build the application by running "make"

We can now push our application to DotCloud:

$ dotcloud push ramen ramen-on-dotcloud/
# upload /home/.../ramen-on-dotcloud/ ssh://dotcloud@uploader.dotcloud.com:21122/ramen
# rsync
[...]
sent 8.11K bytes  received 352 bytes  995.06 bytes/sec
total size is 14.78K  speedup is 1.75
Deployment for "ramen" triggered. Will be available in a few seconds.
2011-06-28 04:27:34 [api] Waiting for the build. (It may take a few minutes)
2011-06-28 04:27:48 [www.0] service booted
2011-06-28 04:27:48 [www.0] The build started
2011-06-28 04:27:48 [www.0] Fetched code revision rsync-1309235251.44
2011-06-28 04:27:51 [www.0] Reloading nginx configuration: nginx.
2011-06-28 04:27:51 [www.0] The build finished successfully
2011-06-28 04:27:51 [api] Deploy finished

Deployment finished successfully. Your application is available at the following URLs
www: http://d07c100d.dotcloud.com/

A random URL has been generated for each web service in your application (it won’t be http://d07c100d.dotcloud.com/ for your app, but something else). Point your browser to this URL to see your new service in action!

If you want to attach a better URL to your application, read the Custom Domains documentation.

Layout of an Opa Service

Once pushed on DotCloud your application will be installed into “/home/dotcloud/” here is how it is organized:

home/
└── dotcloud/
    ├── current/
    │   ├── dotcloud.yml     # Your code lives here: /home/dotcloud/current/
    │   ├── main.opa         # Your application code
    │   ├── main.exe         # Your application
    │   ├── Makefile         # Your application build script
    │   ├── postinstall*     # Optional post installation script
    │   └── supervisord.conf # Run your application with the help of Supervisor
    ├── environment.json     # Hold informations on your stack and your environment variables
    └── environment.yaml     # Same thing but in YAML

Troubleshooting

Your Opa application is launched inside Supervisor, a very useful program to run and monitor background tasks. If your application ever crash, Supervisor will restart it.

You can check that your application has been built and started successfully with the following command:

$ dotcloud run ramen.www supervisorctl status
opa-app                          RUNNING    pid 975, uptime 0:03:20

Supervisor also takes care of the logs for you and conveniently store and rotate them in “/var/log/supervisor”. You can watch the logs in realtime from your computer with the command:

$ dotcloud logs ramen.www

Press ctrl+c to stop watching them.

Caveats

Opa on DotCloud should be considered as a beta service, in particular it doesn’t support scaling features yet.