Search code examples
node.jsmongodbibm-cloudcompose-dbpencilblue

Compose-for-mongodb Bluemix connection with pencilblue


Currently, I am using Bluemix to deploy and host a website with PencilBlue. My issue lies in the connection of a storage service "compose-for-mongo" and the pencilblue framework. This connection is done through the VCAP JSON. The VCAP comes with the following structure;

{
    "compose-for-mongodb": [
        {
            "credentials": {
                "db_type": "mongodb",
                "name": "**************************************",
                "uri_cli": "**************************************",
                "ca_certificate_base64": "*********************************************************************",
                "deployment_id": "*********************************",
                "uri": "******************************************************"
            },
            "syslog_drain_url": null,
            "label": "compose-for-mongodb",
            "provider": null,
            "plan": "***********",
            "name": "************************",
            "tags": [
                "big_data",
                "data_management",
                "ibm_created"
            ]
        }
    ]
}

As I understand this, "compose-for-mongodb" is a cluster instead of a server. We need to make the connection between PencilBlue and this "cluster" through the VCAP JSON. Currently, we are trying to lead the JSON parse in the config.js like so:

 if (typeof process.env.VCAP_SERVICES === 'string') {
        try {
            var vcapServices = JSON.parse(process.env.VCAP_SERVICES);
            var vcapMongo = vcapServices['compose-for-mongodb'][0].credentials;

            var uri = vcapMongo.uri;

            mongoConfig.servers = [
                uri
            ];

            var userPassword = uri.split('mongodb://')[1].split('@')[0].split(':');

            mongoConfig.authentication = {
                un: userPassword[0],
                pw: userPassword[1]
            };

            var db = uri.split('?uri=')[0].split('/')[1];

            mongoConfig.options.mongos = {
                ssl: true,
                sslValidate: true,
                sslCA: [new Buffer(vcapMongo.ca_certificate_base64, 'base64')],
                poolSize: 1,
                reconnectTries: 1
            };

            mongoConfig.name = db;

We have tried multiple ways without any success.

Has anyone encountered this problem yet? Is there any documentation on this subject?

Steps to Reproduce:

Create a Bluemix Node App and connect it with the "compose-for-mongodb" storage service.

PencilBlue Version: 0.8.0

Environment Description: Node.js SDK in Bluemix and compose-for-mongodb service connected


Solution

  • I've had experience and success connecting the pencilblue framework with a NoSQL datasource such as Compose-for-mongodb. Here's a sample repo with some handy deploy to bluemix buttons that sets everything up for you - if you'd like a turnkey approach (Caveat: Some patience is required :-) The pipeline script includes some hard coded delays (~8 mins) to accommodate uncertainty with service instantiation). For your particular question, the repository's config.js should help. Finally, this repo also utilizes a media provider plugin using the Bluemix Object Storage service within this repo.

    Here's an excerpt:

    [....]
    
    try {
      var services = JSON.parse(process.env.VCAP_SERVICES);
      // look for a service starting with 'mysql'
      // MySQL is the only one supported by Ghost right now
      for (var svcName in services) {
          if (svcName.match(/^compose-for-mongodb/)) {
              mongoCreds = services[svcName][0]['credentials'];
              var uriObject = mongodbUri.parse(mongoCreds.uri)
              mongoCreds.host = uriObject.hosts[0].host
              mongoCreds.port = uriObject.hosts[0].port
              mongoCreds.user = uriObject.username
              mongoCreds.password = uriObject.password
              mongoCreds.client = 'mongo';
              mongoCreds.userpass = mongoCreds.user + ":" + mongoCreds.password + "@"
              mongoCreds.db = uriObject.database;
          }
      }
    }
    
    [....]
    
    "db": {
            "type": mongoCreds.client,
            "servers": [
              "mongodb://" + mongoCreds.userpass + mongoCreds.host + ":" + mongoCreds.port
            ],
            "name": mongoCreds.db,
            "options": {
              "server": {
                 "ssl": cloud,
                 "sslValidate": cloud,
                 "sslCert": Buffer.from(mongoCreds.ca_certificate_base64, 'base64').toString('ascii'),
                 "sslCA" : [Buffer.from(mongoCreds.ca_certificate_base64, 'base64').toString('ascii')]
              }
            },
            "writeConcern": "majority",
            "query_logging": false,
            "authentication": {
              "un": mongoCreds.user,
              "pw": mongoCreds.password
            }
        },
    
    [....]