Updating an Old Node.js Project
Note: This is a slightly modified version of an earlier post. See changes at bottom.
My first "serious" NodeJS application, NextQ, a site to search for upcoming Dog Agility Trials, has been sputtering along for several years. Not much used, but it's been reasonably reliable. It was hosted on OpenShift Online 2, which hosted both the Node code and the MongoDB. In September I started getting emails that OpenShift 2 was in "sunset" mode and I should upgrade to OpenShift 3. While I was at it, may as well update the application. That part proved to be fairly simple.
## Updating the Application NPM has a nice command, `npm outdated`, to see what's up with your current modules in package.json. My results were:
> npm outdated Package Current Wanted Latest Location body-parser 1.15.0 1.15.2 1.17.2 nextq.info cheerio 0.20.0 0.20.0 1.0.0-rc.2 nextq.info compression 1.6.1 1.6.2 1.7.0 nextq.info errorhandler 1.4.3 1.4.3 1.5.0 nextq.info express 4.13.4 4.13.4 4.15.4 nextq.info express-session 1.13.0 1.13.0 1.15.5 nextq.info method-override 2.3.5 2.3.9 2.3.9 nextq.info mocha 1.14.0 1.14.0 3.5.0 nextq.info mongodb 2.1.16 2.1.21 2.2.31 nextq.info morgan 1.7.0 1.7.0 1.8.2 nextq.info multer 1.1.0 1.1.0 1.3.0 nextq.info request 2.71.0 2.71.0 2.81.0 nextq.info serve-favicon 2.3.0 2.3.2 2.4.3 nextq.info xmldoc 0.4.0 0.4.0 1.1.0 nextq.info
As you can see, many were way out of date. The above list doesn't include Jade, which was at 1.11.0. It's successor, renamed to pug, was at 2.0.0-rc.4 I decided to update neither Jade nor cheerio to "release candidate" versions, especially of major semantic revisions. I'm not using any fancy features of most of these packages, but let's not push it.
Not sure if there is an automatic way to tell npm to update most but not all of package.json, and it was simplest
to carefully manual edit package.json. Then run
npm update and everything looked good.
...express deprecated req.param(name, default): Use req.params, req.body, or req.query instead at orgs\UKI.js:108:64
I liked having the "default" parameter in the function call, but easy enough to change to
req.params.something || ''.
Everything continued to run fine. In "local" mode, the app connects to a small mLab copy of my small MongoDB DB.
I was very happy - updating the code part of the project was relatively simple and painless.
## Updating OpenShift to V3
This part had more hassles. First you login to OpenShift Online 3 Starter (starter == free). Since I already had a RedHat account, no hassle. Had to add my Name and Location, then select a server location (California). It took quite a while while "Your account is being provisioned". I had to hit refresh and login again to get to the console.
Though I mainly used their web console, you probably want to download their CLI, "oc".
Your new project has a "name" and a "display name". Seems like overkill to me, and at this stage who knows where there is any difference?
Picked same name, nextq, for both, and gave a brief description. Then you Browse the Catalog for setting up the project. I chose Node.js v6, and one nice feature is that you can auto-connect to an existing GitHub or GitLab project, so connecting to my updated code was easy. Then setup Mongodb, version 3.2. It has a Username, Password, and Dayabase name. I tried reducing the volume capacity from 1 Gig, cause my DB is tiny, but there's a minimum of 1 Gig. It wasn't clear what the all-important Mongo URI was.
At this time, my "pods" were setup, and I could rsh:
>oc get pods NAME READY STATUS RESTARTS AGE mongodb-1-56klw 1/1 Running 0 1d nextq-1-build 0/1 Error 0 1d >oc rsh nextq-1-build sh-4.2$ exit (to exit...)
>oc port-forward mongodb-1-56klw 27017:27017
allowed me to connect via >mongo or Compass. However, at that point, not much worked. I could see the existing empty DB, but never succeeded in reliably adding the collections I need. In fact, all through this conversion, the OpenShift MongoDB was extremely unreliable. I was constantly getting "server instance pool was destroyed". Another big issue is computing the Mongo URI. Yes, one can compute it from process.env. But oh my God, what a hassle of boilerplate. Much simpler to just add an environment variable, MONGO_URL, which is how my code worked in OpenShift 2.
Since the OpenShift Mongo was flaky, I fell back to my mLab instance. Every few weeks it dies with a "server instance pool was destroyed" error, but a restart seems to do the trick.
As far as the new OpenShift infrastructure, which features Docker / Kubernetes, maybe the web interface needs some clarity.
If you know nothing about Kubernetes, like I did, it's a bit overwhelming, so check this out: O'Reilly is offering a free excerpt of Kubernetes, Up & Running.
Most people will eventually want to point their DNS server at their app. You do that with routes.
You start with one route, pointing your project name at the server, in my case, nextq -> http://nextq-nextq.xxxx.starter-us-west-1.openshiftapps.com, where xxx is a jumble of letters and numbers for your server. Not sure why "nextq" is in the URL twice. The desired structure is
Name Hostname Routes To Target Port TLS Termination wwwnextqinfo http://www.nextq.info nextq 8080-tcp nextqinfo http://nextq.info nextq 8080-tcp nextq http://nextq-nextq.a3c1.starter-us-west-1.openshiftapps.co nextq 8080-tcp
On my NameCheap DNS, for nextq.info, I have
Source URL Destination URL (on the Domain tab) @.nextq.info -> www.nextq.info Type Host Value (on the Advanced DNS tab) CNAME Record www nextq-nextq.a3c1.starter-us-west-1.openshiftapps.com. TXT Record @ google-site-verification=somelongvalue URL Redirect Record @ http://www.nextq.info Unmasked
When you type either nextq.info or www.nextq.info in your browser, you get redirected to www.nextq.info and (unseen) to OpenShift. A raw "apex" or "naked" root redirect can be problematic, so that's why I route everything to www.
In conclusion, the transition is working. But, either I need to learn Kubernetes / Docker (they are on my list!)
or OpenShift needs to do more hand-holding or a better CLI.
For V2 they had a nice book, Getting Started with OpenShift that maybe should be updated.
Update Nov 26 2017
Never really figured out the OpenShift web interface, nor did their service become more reliable. In fact, the whole build / deploy process degraded until it hung completely. I switched to Heroku, which sports a more "traditional" Node.js as a service interface, and so far am very happy. More details here