Morgan Conrad

Updating an Old Node.js Project

Tags: all JavaScript NodeJS OpenShift     Nov 28 2017

Note: This is a slightly modified version of an earlier post. See changes at bottom.

Intro

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.

As a relative newbie to JavaScript and Node, I use the WebStorm IDE for much of the development. Did a minor update of it from 2016.3.3 to 2016.3.4. There's newer versions but they require a new download, not a patch, so ignored them. Somewhat to my surprise, everything ran fine with WebStorm on localhost. There were three deprecation warnings, all in the same file in nearby lines.

...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...)

You can interact with your MongoDB (to initialize it) from rsh, but if you are a wimp and want to use you normal tools, or a GUI like Compass, the alternative is Port Forwarding

>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