This is a simple log of what I have done during past few days trying to deploy a simple app to OpenShift. I thought it would be quite easy but apparently this is beyond my knowledge. My application is a simple Hello World app. The only real requirement is that I wanted this app to compile with Scala 2.10.
I won’t discuss how to set up the application on OpenShift (unless it is really needed). The only thing worth mentioning is that you will need a Do-It-Yourself type.
There is no SBT on OpenShift. That’s right, you have to get it yourself. OpenShift however provides a nice way of storing things with its data directory (available at $OPENSHIFT_DATA_DIR) and it’s action hooks are the way to go in this case. After some trial and error this is the script I came up with.
if [[ -d sbt ]]; then
echo "SBT installed"
curl -o sbt.tgz http://scalasbt.artifactoryonline.com/scalasbt/sbt-native-packages/org/scala-sbt/sbt/0.12.2/sbt.tgz
tar zxvf sbt.tgz sbt
This script basically downloads SBT from its site but only if SBT folder is not present in the data directory. Then the downloaded tgz archive gets unpacked and SBT is ready to be used.
Now this is the part I spent most time with and unfortunately I can’t make it fully work :( There were several issues with building using SBT, but after some time it almost worked. Here’s the build script I developed that semi-works.
This took a while to figure out. Let’s go line by line to see what everything is needed for. Lines 1, 2 and 3 define three variables that are required to run SBT (they could have been moved to pre_build script to keep everything SBT related in one place).
* Line 1 simply defines the path to SBT directory.
* Line 2 is a variable with path to folder SBT uses to store its data. On OpenShift you don’t have permission to write to your home directory, hence a need for custom dir.
* Line 3 is like line 2 except for Ivy cache.
* Line 5 then switches to the repository directory. This is the place where your sources reside and this is mostly the place where you should start your build at.
* Line 7 is a simple invocation of the SBT with the predefined settings. I’m generating a start script here (using xsbt-start-script-plugin) and that’s why I only include this goal.
This somewhat works. Considering the requirements we now have a project that uses Scala 2.10. But there are now two things to consider.
At first in pre_build I downloaded SBT 0.12.2 and in project build.settings I had SBT setup to 0.12.1. This triggered a compilation of ‘compiler-interface’.
remote: [info] Compiling 1 Scala source to /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/scala-2.10/classes...
remote: [info] 'compiler-interface' not yet compiled for Scala 2.10.0. Compiling...
But this failed. Compilation wouldn’t finish and the process was killed. Small fix in build.properties and upping the actual SBT version to 0.12.2 fixed this – no more recompilation of ‘compiler-interface’.
When you push your project to OpenShift now, it downloads SBT, unpacks it and tries to build your project. And it fails with the same error as above.
[info] Loading project definition from /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/project
[info] Set current project to YAT Server (in build file:/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/)
[debug] Initial source changes:
[debug] added: Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
[debug] modified: Set()
[debug] Removed products: Set()
[debug] Modified external sources: Set()
[debug] Modified binary dependencies: Set()
[debug] Initial directly invalidated sources: Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
[debug] Sources indirectly invalidated by:
[debug] product: Set()
[debug] binary dep: Set()
[debug] external source: Set()
[debug] Initially invalidated: Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
[debug] Recompiling all 1 sources: invalidated sources (1) exceeded 50.0% of all sources
[info] Compiling 1 Scala source to /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/scala-2.10/classes...
[debug] Running cached compiler 12a6774, interfacing (CompilerInterface) with Scala compiler version 2.10.0
[debug] Calling Scala compiler with arguments (CompilerInterface):
[debug] Scala compilation took 34.206682197 s
[debug] Step 2 changed sources and immdediate dependencies:
[debug] Non-trivial strongly connected components:
[debug] Step 2 invalidated sources:
[info] Wrote start script for mainClass := Some(pl.apptile.yat.YAT) to /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/start
This is quite puzzling and I can’t figure out why automatic build doesn’t work. What’s worth mentioning though is that it does work when you change Scala to 2.9.2. But it’s against requirements and hence I stopped at this point, unable to continue.
While I was really happy that most of the things were quite easy to start with, inability to compile the sources makes it a no-no for further work, like actually starting a spray-can server. My application was a Hello World app and if this can’t compile… Sorry OpenShift, for now I’m switching to CloudFoundry to see how it fares.