1
votes

I would like to deploy a Node.JS app on Cloud Foundry. I follow the following steps:

  1. Add the engines part in the package.json

    {
      "name": "vsapc",
      "version": "1.0.0",
      "description": "Application Name",
      "main": "server/app.js",
      "scripts": {
        "start": "node server/app.js",
        "backup": "node backup.js",
        "restore": "node restore.js",
        "seed": "node server/seed/Seed.js",
        "postinstall": "node install.js"
      },
      "directories": {
        "test": "test"
      },
      "dependencies": {
        "bcrypt-nodejs": "0.0.3",
        "body-parser": "^1.15.2",
      "cfenv": "^1.0.3",
        "express": "^4.14.0",
        "jsonwebtoken": "^7.1.9",
        "mongodb": "^2.2.5",
        "mongoose": "^4.6.3",
        "mongoose-seed": "^0.3.1",
        "morgan": "^1.7.0",
        "promise": "^7.1.1",
        "prompt": "^1.0.0",
        "winston": "^2.2.0",
        "winston-daily-rotate-file": "^1.4.0"
      },
      "engines": {
      "node": "6.11.*",
      "npm": "5.*"
      },
      "author": "",
      "license": "ISC"
    }
    
  2. I create the manifest.yml

---
applications:
- name: Policy_Studio
  memory: 2048MB

  env:
    NODE_ENV: production
  1. I used the following to connect in install.js:
const vcapServices = JSON.parse(process.env.VCAP_SERVICES);
            let mongoUrl = '';
            mongoUrl = vcapServices.mongodb[0].credentials.uri;

            mongoose.connect(mongoUrl,{useMongoClient: true}, function (err){
              if (err) {
                  console.log("Database connection responded with: " + err.message);
                  console.log("Is your server.config.json up to date?");
                  process.exit(1);
                  return
              }
              console.log("Connected to database.");
  1. and the following in app.js:
Server.prototype.connectDatabase = function (url) {
          mongoose.Promise = Promise;
          const vcapServices = JSON.parse(process.env.VCAP_SERVICES);
          let mongoUrl = '';
          mongoUrl = vcapServices.mongodb[0].credentials.uri;
          mongoose.connect(mongoUrl,{useMongoClient: true});
          mongoose.connection.on("error", function (err) {
              log.error(err)
          });
          mongoose.connection.once("openUri", function () {
              log.info("Connected to DB")
          })
      };
  1. connect by command line to SCAPP and push the app with cf push

  2. As i don't have the MongoDB on the cloud i have an error

  3. I build a MOngoDB service on the cloud and bind directly the app through the web GUI

  4. On the gui i click restage button for my app
  5. I have the error
Database connection responded with: failed to connect to server 
[2xtorvw9ys7tg9pc.service.consul:49642] on first connect [MongoError: 
connect ECONNREFUSED 10.98.250.54:49642]
  1. I add the service mongoDB in my manifest and cf push my application
  2. Still the same error as in point 9

  3. I tried to change the connection in install.js

Thank you for your help

2
you created your container on internal App Cloud 2017-10-03T06:26:09Z and I can confirm the container is healthy. Please post more details about your code and setup (app) - Josefine
Thank you for your support. I didn't code the app. I know that it was made not made to be deploy on the cloud and the application without modification works on a local machine. For the code I don't know what you would need more precisely. Can we discuss in PM ? - jerem0808
please write every step what you did (manifest, commercial app product sources, push command) to Scapp Internal, INI-INO-SWD. Here are too less info to help you - Josefine

2 Answers

3
votes

While your parsing of VCAP_SERVICES appears to work (you get a URL containing a hostname & port), i highly recommend to leverage one of the existing libraries for it for further projects: https://www.npmjs.com/package/cfenv

Still, please that the parsing of your mongo credentials is properly working (cf e ${app_name}, look for VCAP_SERVICES, manually compare)

If you want to test your service with independent code, here is a sample app i quickly threw together to test all mongodb services bound to it:

package.json:

{
  "name": "mongo-tester",
  "version": "1.0.0",
  "description": "tests all mongodbs via VCAP_SERVICES",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Michael Erne",
  "license": "MIT",
  "dependencies": {
    "async": "^2.5.0",
    "cfenv": "^1.0.4",
    "lodash": "^4.17.4",
    "mongodb": "^2.2.31"
  }
}

server.js:

var cfenv = require('cfenv'),
    _ = require('lodash'),
    http = require('http'),
    async = require('async'),
    MongoClient = require('mongodb').MongoClient


var appEnv = cfenv.getAppEnv();

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Return something for CF Health Check\n');
}).listen(appEnv.port);

var services = _.values(appEnv.getServices());
var mongodbs = _.filter(services, { label: 'mongodb' });

async.eachLimit(mongodbs, 1, function (m, callback) {
  MongoClient.connect(m.credentials.database_uri, function (err, db) {
    if (err) {
      return callback(err);
    }
    db.collection("debug").insertOne({"test": true}, function(err, res) {
      if (err) return callback(err);
      console.log("document inserted successfully into " + m.credentials.database_uri);
      db.close();
      return callback(null);
    });
  });
}, function (err) {
    if (err) {
      console.log(err.stack || err);
      console.log('---> mongodb connection failed <---');
      return;
    }
    console.log('---> connection to all BOUND mongodb successful <---');
});

It should print something like the following in its logs if it can connect to any of the bound mongodb services:

document inserted successfully into mongodb://xxx:[email protected]:1337/databaseName
---> connection to all BOUND mongodb successful <---

If this fails with similar errors, the service instance seems broken (wrong url/port being reported). I would just recreate the service instance in that case and try again.

1
votes

Finally we have found the problem. The cloud foundry is not allowing to access the MongoDB service during the postinstall phase. So we changed it to prestart and it worked. Thank you for your help