A couple of years ago we did two “secret shopper” posts about our fairly good experience using Red Hat OpenShift and our fairly dismal experience using CloudFoundry – then a VMware technology. CloudFoundry is now in the portfolio of a new company known as Pivotal, which has just launched a Version 2 of CloudFoundry.com. Red Hat has just launched a new version of OpenShift with private PaaS support, and we are re-visiting both offerings with a view to understanding how to adopt them, using an application we are developing for various other purposes.
However, we aren’t going to go out of our way to adopt PaaS for this application. If it doesn’t work, or if it doesn’t fit with the way we work, we will only go to commercially reasonable levels of effort to bend our Application Lifecycle Management (ALM) processes to fit.
In our previous posts we focused on a fairly basic scenario of deploying from a developer workstation. This time we are focusing on a more real-world ALM scenario. In this post we explain the nature of the problem. In two subsequent posts we will deal with our experiences of resolving these problems on OpenShift and CloudFoundry.
Our application is MySQL/Tomcat/Apache and Groovy/Grails with a small amount of plain Java on the server-side and a completely custom client-side written in Javascript. This, in turn, makes very heavy use of the dojo javascript libraries. There is also a Command Line Interface (CLI) written in groovy and packaged as a separate executable jar file.
The application is developed in four Eclipse projects – one for the Grails/Groovy/Java, one for the Javascript libraries, one for the CLI, and one for the tests, all built using the Groovy/Grails tool suite, which is based on Eclipse.
The development team shares code using a Subversion (svn) repository and a Trac issue management system. Every night a Jenkins build server checks out the contents of the svn repository and creates a nightly build comprising a small number of artefacts – a war file, the CLI jar, and the javascript libraries packaged as a zip file. Jenkins then copies and installs these on a test server using some custom scripting and executes the automated tests. From time to time we run additional manual testing against a nightly build, and this is then “declared” as stable, the revision is tagged in svn, and the build is deployed manually into various production environments.
Our first “real-world” decision is that whilst the PaaS vendors have spent a lot of time making it easy for developers to use the PaaS, we won’t be using the PaaS for development of this application. The developers work with a local Eclipse environment on their desktops and run the application using “grails run-app”, which does a great job of handling incremental changes without rebuilding a war file. There would be no benefit in the developers using the PaaS because the building and deploying of the war file would just slow down the development cycle and make it dependent on connectivity to the cloud—developers sometimes work disconnected.
However, we do see value in using PaaS later on in the lifecycle to run our nightly integration tests and for hosting a demonstration environment based on the latest stable build.
As far as production hosting of this application is concerned, we don’t yet see much of a role for PaaS. We still envisage most production deployments would be manual, on in-house servers. These would typically be virtualized, but very few enterprises currently have an in-house private PaaS that we can simply deploy to. Our deployments would be configured to specific requirements of scalability, performance, and security. Initially, many deployments are put on an isolated network that doesn’t even have internet access and must remain isolated until the enterprise performs its own penetration testing. In some cases production deployments remain permanently isolated. In isolated networks public PaaS would never be an option. Over time we may see some adoption of PaaS by enterprises, but we can’t rely on it as our only deployment mechanism.
This leads to a key point —the artefacts we deploy and test on the PaaS must be identical to those we deploy using other mechanisms. This is required to ensure traceability between the software deployed in production and that which has been tested. We can’t have two different sets of artefacts, one for the PaaS and one for production. The checksums on the files have to match.
PaaS generally likes war files, and our software predominantly packages into a war file. However, there are a few complexities that need to be addressed:
- Rather than embedding static content (mainly custom Javascript and dojo libraries) in the war file for Tomcat to serve out, we package this in a second file which is unzipped into the web root to be served by Apache.
- Dojo libraries are by default served by Apache from the web root, but they can also be served from the Google or Yandex CDN depending on the application deployment scenario. Clearly, the CDN isn’t going to work if the application is on a LAN that has no internet access.
- There is an external config file in /etc which is used to specify the location of the Javascript libraries, to define the database connection, and to specify the URL of the application for one or two hard-coded links (that we’d like to get rid of but haven’t quite managed to yet).
So in planning for our scenario (which we suggest may be representative of many real-world scenarios), this is what came up:
- Get our build server (Jenkins) to deploy to the PaaS – perhaps there is a plugin that does this?
- Find some way of dealing with the static content that is usually packaged outside of the war file. In the case of dojo this is likely going to be by pointing at the CDN (if the user can see the public PaaS they can see the CDN). However this doesn’t apply to our own Javascript libraries and we need to find a way of getting the PaaS to serve them out.
- Reconcile the way the PaaS defines external services (i.e. databases) with the way the application currently configures them through files in /etc.
- Pass back the PaaS-specified URL into the application config for use in hard-coded links
We’ll see how we get on with the two PaaS in the next couple of posts. Other issues may, of course, arise.