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:
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:
{ "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:
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:
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.
No comments:
Post a Comment