Deploying akka-http app to Cloud Foundry
In a preceding post I had gone over the steps to deploy a simple akka-http app to Cloud Foundry. The gist of it was that as long there is a way to create a runnable fat(uber) jar, the deployment is very straightforward – Cloud Foundry’s Java buildpack can take the bits and wire up everything needed to get it up an running in the Cloud Foundry environment.
Here I wanted to go over a slightly more involved scenario – this is where the app has an external database dependency say to a MySQL database.
In a local environment the details of the database would have been resolved using a configuration typically specified like this:
1 2 3 4 5 | sampledb = { url = "jdbc:mysql://localhost:3306/mydb?useSSL=false" user = "myuser" password = "mypass" } |
If the Mysql database were to be outside of Cloud Foundry environment this approach of specifying the database configuration will continue to work nicely. However if the service resides in a
Cloud Foundry market place , then the details of the service is created dynamically at bind time with the Application.
Just to make this a little more concrete, in my local PCF Dev, I have a marketplace with “p-mysql” service available.
And if I were to create a “service instance” out of this:
and bind this instance to an app:
essentially what happens at this point is that the application has an environment variable called VCAP_SERVICES available to it and this has to be parsed to get the db creds. VCAP_SERVICES in the current scenario looks something like this:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | { "p-mysql" : [ { "credentials" : { "hostname" : "mysql-broker.local.pcfdev.io" , "jdbcUrl" : "jdbc:mysql://mysql-broker.local.pcfdev.io:3306/myinstance?user=user\u0026password=pwd" , "name" : "myinstance" , "password" : "pwd" , "port" : 3306 , "uri" : "mysql://user:pwd@mysql-broker.local.pcfdev.io:3306/myinstance?reconnect=true" , "username" : "user" }, "label" : "p-mysql" , "name" : "mydb" , "plan" : "512mb" , "provider" : null , "syslog_drain_url" : null , "tags" : [ "mysql" ] } ] } |
This can be parsed very easily using Typesafe config, a sample (admittedly hacky) code looks like this:
01 02 03 04 05 06 07 08 09 10 | def getConfigFor(serviceType: String, name: String): Config = { val vcapServices = env( "VCAP_SERVICES" ) val rootConfig = ConfigFactory.parseString(vcapServices) val configs = rootConfig.getConfigList(serviceType).asScala .filter(_.getString( "name" ) == name) .map(instance => instance.getConfig( "credentials" )) if (configs.length > 0 ) configs.head else ConfigFactory.empty() } |
and called the following way:
1 | val dbConfig = cfServicesHelper.getConfigFor( "p-mysql" , "mydb" ) |
This would dynamically resolve the credentials for mysql and would allow the application to connect to the database.
An easier way to follow all this may be to look at a sample code available in my github repo here – https://github.com/bijukunjummen/sample-akka-http-rest.
Reference: | Deploying akka-http app to Cloud Foundry from our JCG partner Biju Kunjummen at the all and sundry blog. |