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