Categorieën
C++

C++ Application on CloudFoundry

CloudFoundry

My employer decided to go with Pivotal CloudFoundry as one of the cloud providers for the company. I attended a launch event for all developers. Pivotal delivered a talk on using the platform and used a bit of Go and a lot of Java in the examples. Interesting, but real performance junkies want to use an application that is compiled to a binary that can run natively on the hardware(which is always virtualized in a cloud environment). At least I want to be able to do that. So I decided to use C++ to create a TimeZoneService that translates a date from a certain time zone into a date in a different time zone. I will show how to deploy this service to CloudFoundry (not only pivotal, but also IBM uses CloudFoundry as platform for their cloud offerings).

TimeZoneService

The service is rather simple. You send it a JSON with a conversion request and you get a JSON with a converted date or an error back. An example JSON for the request is:

{
"TimeZoneFrom":"Europe/London", "TimeZoneTo":"Europe/Amsterdam",
"Year":2017,
"Month":3,
"Day":20,
"HourIn24H":15,
"Minute":25 
}

You will get a result that looks like the following:

{
"ConvertedDateTime": "2017-03-20 16:25:00.000000000 CET" 
}

Development

Now the interesting stuff. I use CLion as a my IDE. CLion uses cmake for the build. I used conan package manager for a while, but I’m still not convinced that conan suits my needs. One of the libraries I use doesn’t have (all) the debug symbols in the library. While I can choose to build the library with debug symbols myself with the help of conan, I’m not able to build the library with my own compiler and linker flags. The end result is that still some of the details are missing in the library. So in the end I didn’t use conan for this project. The libraries used are PocoHoward Hinnant’s dateCatch2 and Trompeloeil (the latter two for unit testing and mocking).

As I have no saying in what libraries are installed on the CloudFoundry platform, I should be taking care of delivering all my dependencies to the platform. The easiest way is by use static linked libraries. So you get an executable that has all dependencies available. One to the things that made delivering this more complicated is that the Poco libraries have some circular dependencies, so I changed the installation for my vagrant box (see try it yourself) to have a libPocoAlld.a library to link against.

Some research learned that the CloudFoundry platform is ubuntu based, so I know that I have to compile the TimeZoneService for linux/ubuntu to get an executable that is ABI compatible. After this research things started getting easier (as always when you get the understanding of a subject). To get an app deployed to CloudFoundry, you have to use the CF command line tool. For a native compiled binary you have to use the binary-buildpack. It is very important that your app listens to the right port. The CloudFoundry platform uses an environment variable to communicate the port to the application. When the app starts it uses the PORT environment variable for the port to listen to on localhost. It is important to use localhost instead of a dns name, because CloudFoundry decides on which host the app will be deployed. You can therefore never now in advance what hostname to use, but fortunately localhost is always available. To deploy the app on CloudFoundry, you need to execute the following command:

cf push TimeZoneService -c './TimeZoneService' -b https://github.com/cloudfoundry/binary_buildpack.git

Bummer, the app is not deployed. See the screenshot.

Failed CloudFoundry deployment

So I need to recompile with static linking against libgcc and libstdc++ and push the app again to CloudFoundry.

Now the app is deployed. How to access the newly deployed app depends on your CloudFoundry account and settings. You can use curl to request a time zone conversion. The example here is for my trial account.

curl -H "Content-Type: application/json" -X POST -d '{ "TimeZoneFrom":"Europe/London", "TimeZoneTo":"Europe/Amsterdam", "Year":2017, "Month":3, "Day":20, "HourIn24H":15, "Minute":25 }' timezoneservice.cfapps.io/ConvertDateTime
curl -H "Content-Type: application/json" -X GET timezoneservice.cfapps.io/AllTimeZones

Try it yourself

When you want to try it yourself, you can go to my github and clone the repository. You will get a vagrant file that contains the installation of an ubuntu version on which you can compile the app. You will need an account for a CloudFoundry cloud provider. I cannot provide you with one, but you can try to get it from pivotal or one of the other providers.

$ git clone https://github.com/hklabbers/CloudFoundryTest.git
  • Go into the vagrant folder of your just cloned repository and start the virtual machine:
$ vagrant up
  • Login to your vagrant box by issuing the following command:
$ ssh -p 2222 vagrant@localhost
  • Go into the project folder with the following command:
cd /workspace/TimeZoneService/cmake-build-debug
  • Execute CMake and make:
  •  cmake ../
  • make
  • The executables will be in the bin directory. First run the tests:
bin/TimeZoneServiceTest
  • Now you can try to run it on your cloudfoundry.
  • After logging in with cf login, you should set a target org and space cf -o ORG -s SPACE.
  • Go into the bin directory of your project, remove the TimeZoneServiceTest executable (unless you want to deploy that also, which is useless). Now you can deploy with:
cf push TimeZoneService -c './TimeZoneService' -b https://github.com/cloudfoundry/binary-buildpack.git
  • The command line push informed you were you can find your deployed app. TimeZoneService was deployed at route timezoneservice.cfapps.io.