<commit_before>---
authors: <NAME> <<EMAIL>>, <NAME> <<EMAIL>>
state: publish
---

<!--
    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->

<!--
    Copyright 2016 Joyent, Inc.
-->

# RFD 59: Update Triton to Node.js v4-LTS

Triton circa 2016 uses node 0.10 heavily for its services, with node 0.8 and
0.12 being used in a few places. 0.8 is already EOL, with 0.10 EOL on October 1,
and 0.12 EOL on December 31. Node.js v4 is currently specified for Long-Term
Support (LTS), and will remain supported until April 2018.

It is not critical for internal services to be updated to LTS, although it is
desirable, but external services (e.g. Cloudapi and sdc-docker) should be
updated in order to keep abreast of security fixes.

Expected work:
- Running node v4 in the global zone has some challenges. See the
  "Node in the GZ" section below.
- There will be a slog of updating node modules dependencies to those building
  cleanly against and supporting node v4 -- including dealing with
  incompatibilities when this involves crossing major versions.
  See the "Node modules" section below.
- Then there remains to be seen if there are subtle issues that result from
  a new major version of node. For example, event ordering changes, possible
  memory leaks.


## Current Status

- The 'imgapi' image is now using node v4 (IMGAPI-587)
- A number of modules have been updated to have node v4 support. See the
  [Node modules](#node-modules) section below.
- 'sdcnode' now includes node v4 builds for usage both in zones using
  sdc-minimal-multiarch-lts@15.4.1 as an origin, and in the GZ.


## Order of service updates

The most pressing updates are to external services. These services are exposed
to hostile networks, and thus have the most pressing need of security patches:

* cloudapi (PUBAPI-1310)
* sdc-docker (DOCKER-947)
* muskie (MANTA-2999)
* imgapi (IMGAPI-587, done)
* CMON (CMON-11)
* adminui (ADMINUI-2314)
* portal (PORTAL-2113)

Internal services (including agents) are less pressing.

Dev Note: Here is one way you can get a fairly complete picture of node versions
in use in Triton components:

    mkdir ~/all
    cd ~/all

    # Clone all the repos. Here is a way (thought unfortunately still in a
    # private engadm.git repo):
    engadm clone-repos .

    grep NODE_PREBUILT_VERSION */Makefile


## Node in the GZ

There are some issues that make running Node >=v4.x in the GZ difficult:

- There is a bug in the illumos' runtime linker where a binary that requires
  a lib version newer than that in the platform still runs instead of failing.
  Details from <NAME> and <NAME> here:
  https://gist.github.com/misterdjules/1eb7987dc0d59034efb4
  (and more notes here: https://gist.github.com/misterdjules/eae9ec70dc1d91fb8dd1).
  This issue is just relevant to be away that some binaries might appear to
  run fine until they run into a crash if a newer lib version symbol is
  actually used. Julien indicates that this is likely the case for coming
  Node v7 changes.
- Node v4 and greater require at least gcc v4.8 to build. Our older images
  only have v4.7. This means we need to update to v15.4.x LTS origin images.
- That newer gcc means linking to a gcc runtime that is newer than what is
  provided in the platform. The solution here is to include the needed GCC
  runtime libs with our sdcnode builds and set node's RPATH/RUNPATH to
  pick those up. See TOOLS-1555 and TOOLS-1558 for this work.

As of TOOLS-1558, there is now a sdcnode v4.6.0 build for 'gz' usage. E.g.:

    NODE_PREBUILT_TAG = gz
    NODE_PREBUILT_VERSION = v4.6.0
    NODE_PREBUILT_IMAGE = 18b094b0-eb01-11e5-80c1-175dac7ddf02

Likely will require changing the jenkins job params to build on a slave
using a multiarch-*@15.4.1 image.  See sdc-imgapi.git for an example
(after IMGAPI-587 is complete).


## Node modules

### bunyan

tl;dr: Update to latest 1.x. No compat issues to worry about.

Bunyan >= 1.5.1 supports building against node v4. However it is suggested
that at least Bunyan 1.8.1 be used because it includes this fix to the CLI
to use `bunyan -p` on node 4.x and above:

- [issue #370] Fix `bunyan -p ...` (i.e. DTrace integration) on node
  4.x and 5.x.

The only incompatible change in Bunyan was from 0.x to 1.x with the CLI's
`bunyan -c CODE` option. IOW, there hasn't been an incompatibility in the
node.js module usage and therefore there isn't a reason to not upgrade to
the latest 1.x.


### ldapjs

tl;dr: If you are just building filters for Moray: switch to `moray-filter`.
If you are just building filters for UFDS: switch to `ldap-filter`.
Else if you aren't node-ufds.git or sdc-ufds.git, let's talk and perhaps 0.8.0
is adequate.

If your app is only using the "filters" functionality of ldapjs, it is
suggested that you switch to 'node-ldap-filter'
(https://github.com/pfmooney/node-ldap-filter).

- 1.0.0: This was a large change that added node v4 support (by updating its
  deps), but also incompatibilities for which we don't necessarily grok
  all the implications.

    [<NAME>]
    > 1.0 changed error handling
    > ...
    > IIRC, the circumstances of when error objects are emitted for things like
    > socket errors, etc
    > when/how those errors are emitted

  At this point, switching from 0.7.x to 1.0.0 would require some digging
  and testing. Consider 0.8.0 as an alternative.

- 0.8.0: This was a quiet compatibility release that Patrick added after
  Trent and he discussed the issues here. The branch point was commit
  aed6d2b043715e1a37c45a6293935c25c023ebce -- a number of commits after
  v0.7.1, and the commit upon which node-ufds currently depends -- and
  then it updated dependencies required to get a clean 'npm install' with
  node v4.

- 0.7.1: The last release before 1.0.0. It has a optional dep on
  dtrace-provider@0.2.8, so while it installs with just a warning, there is
  a lot of noise (and dtrace-y features won't work):

    ```
    gyp ERR! node -v v4.5.0
    gyp ERR! node-gyp -v v3.4.0
    gyp ERR! not ok
    npm WARN optional dep failed, continuing dtrace-provider@0.2.8
    [10:45:33 trentm@danger0:~/src/node-ldapjs ((0a88109...))]
    $ echo $?
    0
    ```

- 0.7.0: This has required "dependencies" that don't compile on node v4, e.g.
  dtrace-provider.


### moray

tl;dr: Update to latest, or at least the following commit to get node v4
support. I don't know of any compat issues.


```
commit 31c0902f47408d43bc9684e200b1ee93e13c2477
Author: <NAME> <<EMAIL>>
Date:   Sun Jul 3 19:52:27 2016 +1000

    MORAY-342: updates deps for node 4.x support, try no. 2.
```

## restify

It is suggested that you upgrade to restify 4.x.

If you are updating from before restify v4 beware a breaking change in the
function signature for custom `formatters`. See this comment:
<https://github.com/restify/node-restify/pull/851#issuecomment-251541881>

If you are updating from before restify v3, note this breaking change:

```
- #753 **BREAKING** Include `err` parameter for all \*Error events:
  Error events will all have the signature `function (req, res, err, cb)` to
  become consistent with the handling functionality introduced in 2.8.5.
  Error handlers using the `function (req, res, cb)` signature must be updated.
```

For example if you have `server.on('NotFound', ...)` or similar.


### sdc-clients

For node v4 support, update to sdc-clients@10.0.0 or later. Note that this
version is a major bump that dropped the UFDS client. If you use the UFDS
client from sdc-clients, switch to "ufds@1.2.0" or later.


### ufds

Move to the "1.2.0" release if you can.


### wf-client

Move to "wf-client@0.2.0" or later.
https://github.com/joyent/sdc-wf-client


## How to update a zone to node v4

1. You need a 15.4.x-generation origin image. Until RFD 46 comes along that
   means (a) sdc-minimal-multiarch-lts@15.4.1 plus (b) adding a few pkgsrc
   package beyond minimal. Make changes similar to this to MG:

    ```
    -    "image_uuid": "fd2cc906-8938-11e3-beab-4359c665ac99",
    +    "// image_uuid": "sdc-minimal-multiarch-lts@15.4.1",
    +    "image_uuid": "18b094b0-eb01-11e5-80c1-175dac7ddf02",
         "pkgsrc": [
    +        "coreutils-8.23nb2",
    +        "curl-7.47.1",
    +        "gsed-4.2.2nb4",
    +        "patch-2.7.5",
    +        "sudo-1.8.15"
         ],
    ```

    This set of pkgsrc packages comes from
    <https://github.com/joyent/rfd/tree/master/rfd/0046#q2-base--or-minimal--or-something-in-between>.

    TODO: Is `dateutils-0.3.1nb1` required? IMGAPI is using it right now but
    there is not history for why that package (which isn't included in the RFD
    46 set) was included. For now we should exclude it from future users, and
    test removing it from IMGAPI's current list.

2. Update your Makefile to get a 4.x sdcnode build. Something like this:

    ```
    -NODE_PREBUILT_VERSION=v0.10.46
    +NODE_PREBUILT_VERSION=v4.6.0
     ifeq ($(shell uname -s),SunOS)
            NODE_PREBUILT_TAG=zone
    -       # Allow building on a SmartOS image other than sdc-smartos@1.6.3.
    -       NODE_PREBUILT_IMAGE=fd2cc906-8938-11e3-beab-4359c665ac99
    +       # Allow building on other than image sdc-minimal-multiarch-lts@15.4.1.
    +       NODE_PREBUILT_IMAGE=18b094b0-eb01-11e5-80c1-175dac7ddf02
     endif
    ```

3. Update your Node modules deps and code per the "Node modules" section notes
   above. For a complete example see the change to IMGAPI for this:
   <https://github.com/joyent/sdc-imgapi/commit/7d0b4b7dedc7c36ba1eec23394d009567b6ef35a>

4. To test your changes, one way is to use Jenkins' `TRY_BRANCH` builds:

    (a) Push your changes to a feature branch (of MG and your repo, say,
        sdc-cnapi.git)
    (b) Make a `TRY_BRANCH=<feature branch name>` build in Jenkins.
    (c) Update your COAL to that image, e.g.: `sdcadm up -C experimental cnapi`
    (d) Or possibly build a COAL with your image, by adding something like this
        to `build.spec.local` in your sdc-headnode.git clone:

        ```
        "zones": {
            "cnapi": {
                "source": "manta",<commit_msg>RFD 59: bump the current latest 4.6 node release<commit_after>---
authors: <NAME> <<EMAIL>>, <NAME> <<EMAIL>>
state: publish
---

<!--
    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->

<!--
    Copyright 2016 Joyent, Inc.
-->

# RFD 59: Update Triton to Node.js v4-LTS

Triton circa 2016 uses node 0.10 heavily for its services, with node 0.8 and
0.12 being used in a few places. 0.8 is already EOL, with 0.10 EOL on October 1,
and 0.12 EOL on December 31. Node.js v4 is currently specified for Long-Term
Support (LTS), and will remain supported until April 2018.

It is not critical for internal services to be updated to LTS, although it is
desirable, but external services (e.g. Cloudapi and sdc-docker) should be
updated in order to keep abreast of security fixes.

Expected work:
- Running node v4 in the global zone has some challenges. See the
  "Node in the GZ" section below.
- There will be a slog of updating node modules dependencies to those building
  cleanly against and supporting node v4 -- including dealing with
  incompatibilities when this involves crossing major versions.
  See the "Node modules" section below.
- Then there remains to be seen if there are subtle issues that result from
  a new major version of node. For example, event ordering changes, possible
  memory leaks.


## Current Status

- The 'imgapi' image is now using node v4 (IMGAPI-587)
- A number of modules have been updated to have node v4 support. See the
  [Node modules](#node-modules) section below.
- 'sdcnode' now includes node v4 builds for usage both in zones using
  sdc-minimal-multiarch-lts@15.4.1 as an origin, and in the GZ.


## Order of service updates

The most pressing updates are to external services. These services are exposed
to hostile networks, and thus have the most pressing need of security patches:

* cloudapi (PUBAPI-1310)
* sdc-docker (DOCKER-947)
* muskie (MANTA-2999)
* imgapi (IMGAPI-587, done)
* CMON (CMON-11)
* adminui (ADMINUI-2314)
* portal (PORTAL-2113)

Internal services (including agents) are less pressing.

Dev Note: Here is one way you can get a fairly complete picture of node versions
in use in Triton components:

    mkdir ~/all
    cd ~/all

    # Clone all the repos. Here is a way (thought unfortunately still in a
    # private engadm.git repo):
    engadm clone-repos .

    grep NODE_PREBUILT_VERSION */Makefile


## Node in the GZ

There are some issues that make running Node >=v4.x in the GZ difficult:

- There is a bug in the illumos' runtime linker where a binary that requires
  a lib version newer than that in the platform still runs instead of failing.
  Details from <NAME> and <NAME> here:
  https://gist.github.com/misterdjules/1eb7987dc0d59034efb4
  (and more notes here: https://gist.github.com/misterdjules/eae9ec70dc1d91fb8dd1).
  This issue is just relevant to be away that some binaries might appear to
  run fine until they run into a crash if a newer lib version symbol is
  actually used. Julien indicates that this is likely the case for coming
  Node v7 changes.
- Node v4 and greater require at least gcc v4.8 to build. Our older images
  only have v4.7. This means we need to update to v15.4.x LTS origin images.
- That newer gcc means linking to a gcc runtime that is newer than what is
  provided in the platform. The solution here is to include the needed GCC
  runtime libs with our sdcnode builds and set node's RPATH/RUNPATH to
  pick those up. See TOOLS-1555 and TOOLS-1558 for this work.

As of TOOLS-1558, there is now a sdcnode v4.6.0 build for 'gz' usage. E.g.:

    NODE_PREBUILT_TAG = gz
    NODE_PREBUILT_VERSION = v4.6.0
    NODE_PREBUILT_IMAGE = 18b094b0-eb01-11e5-80c1-175dac7ddf02

Likely will require changing the jenkins job params to build on a slave
using a multiarch-*@15.4.1 image.  See sdc-imgapi.git for an example
(after IMGAPI-587 is complete).


## Node modules

### bunyan

tl;dr: Update to latest 1.x. No compat issues to worry about.

Bunyan >= 1.5.1 supports building against node v4. However it is suggested
that at least Bunyan 1.8.1 be used because it includes this fix to the CLI
to use `bunyan -p` on node 4.x and above:

- [issue #370] Fix `bunyan -p ...` (i.e. DTrace integration) on node
  4.x and 5.x.

The only incompatible change in Bunyan was from 0.x to 1.x with the CLI's
`bunyan -c CODE` option. IOW, there hasn't been an incompatibility in the
node.js module usage and therefore there isn't a reason to not upgrade to
the latest 1.x.


### ldapjs

tl;dr: If you are just building filters for Moray: switch to `moray-filter`.
If you are just building filters for UFDS: switch to `ldap-filter`.
Else if you aren't node-ufds.git or sdc-ufds.git, let's talk and perhaps 0.8.0
is adequate.

If your app is only using the "filters" functionality of ldapjs, it is
suggested that you switch to 'node-ldap-filter'
(https://github.com/pfmooney/node-ldap-filter).

- 1.0.0: This was a large change that added node v4 support (by updating its
  deps), but also incompatibilities for which we don't necessarily grok
  all the implications.

    [<NAME>]
    > 1.0 changed error handling
    > ...
    > IIRC, the circumstances of when error objects are emitted for things like
    > socket errors, etc
    > when/how those errors are emitted

  At this point, switching from 0.7.x to 1.0.0 would require some digging
  and testing. Consider 0.8.0 as an alternative.

- 0.8.0: This was a quiet compatibility release that Patrick added after
  Trent and he discussed the issues here. The branch point was commit
  aed6d2b043715e1a37c45a6293935c25c023ebce -- a number of commits after
  v0.7.1, and the commit upon which node-ufds currently depends -- and
  then it updated dependencies required to get a clean 'npm install' with
  node v4.

- 0.7.1: The last release before 1.0.0. It has a optional dep on
  dtrace-provider@0.2.8, so while it installs with just a warning, there is
  a lot of noise (and dtrace-y features won't work):

    ```
    gyp ERR! node -v v4.5.0
    gyp ERR! node-gyp -v v3.4.0
    gyp ERR! not ok
    npm WARN optional dep failed, continuing dtrace-provider@0.2.8
    [10:45:33 trentm@danger0:~/src/node-ldapjs ((0a88109...))]
    $ echo $?
    0
    ```

- 0.7.0: This has required "dependencies" that don't compile on node v4, e.g.
  dtrace-provider.


### moray

tl;dr: Update to latest, or at least the following commit to get node v4
support. I don't know of any compat issues.


```
commit 31c0902f47408d43bc9684e200b1ee93e13c2477
Author: <NAME> <<EMAIL>>
Date:   Sun Jul 3 19:52:27 2016 +1000

    MORAY-342: updates deps for node 4.x support, try no. 2.
```

## restify

It is suggested that you upgrade to restify 4.x.

If you are updating from before restify v4 beware a breaking change in the
function signature for custom `formatters`. See this comment:
<https://github.com/restify/node-restify/pull/851#issuecomment-251541881>

If you are updating from before restify v3, note this breaking change:

```
- #753 **BREAKING** Include `err` parameter for all \*Error events:
  Error events will all have the signature `function (req, res, err, cb)` to
  become consistent with the handling functionality introduced in 2.8.5.
  Error handlers using the `function (req, res, cb)` signature must be updated.
```

For example if you have `server.on('NotFound', ...)` or similar.


### sdc-clients

For node v4 support, update to sdc-clients@10.0.0 or later. Note that this
version is a major bump that dropped the UFDS client. If you use the UFDS
client from sdc-clients, switch to "ufds@1.2.0" or later.


### ufds

Move to the "1.2.0" release if you can.


### wf-client

Move to "wf-client@0.2.0" or later.
https://github.com/joyent/sdc-wf-client


## How to update a zone to node v4

1. You need a 15.4.x-generation origin image. Until RFD 46 comes along that
   means (a) sdc-minimal-multiarch-lts@15.4.1 plus (b) adding a few pkgsrc
   package beyond minimal. Make changes similar to this to MG:

    ```
    -    "image_uuid": "fd2cc906-8938-11e3-beab-4359c665ac99",
    +    "// image_uuid": "sdc-minimal-multiarch-lts@15.4.1",
    +    "image_uuid": "18b094b0-eb01-11e5-80c1-175dac7ddf02",
         "pkgsrc": [
    +        "coreutils-8.23nb2",
    +        "curl-7.47.1",
    +        "gsed-4.2.2nb4",
    +        "patch-2.7.5",
    +        "sudo-1.8.15"
         ],
    ```

    This set of pkgsrc packages comes from
    <https://github.com/joyent/rfd/tree/master/rfd/0046#q2-base--or-minimal--or-something-in-between>.

    TODO: Is `dateutils-0.3.1nb1` required? IMGAPI is using it right now but
    there is not history for why that package (which isn't included in the RFD
    46 set) was included. For now we should exclude it from future users, and
    test removing it from IMGAPI's current list.

2. Update your Makefile to get a 4.x sdcnode build. Something like this:

    ```
    -NODE_PREBUILT_VERSION=v0.10.46
    +NODE_PREBUILT_VERSION=v4.6.1
     ifeq ($(shell uname -s),SunOS)
            NODE_PREBUILT_TAG=zone
    -       # Allow building on a SmartOS image other than sdc-smartos@1.6.3.
    -       NODE_PREBUILT_IMAGE=fd2cc906-8938-11e3-beab-4359c665ac99
    +       # Allow building on other than image sdc-minimal-multiarch-lts@15.4.1.
    +       NODE_PREBUILT_IMAGE=18b094b0-eb01-11e5-80c1-175dac7ddf02
     endif
    ```

3. Update your Node modules deps and code per the "Node modules" section notes
   above. For a complete example see the change to IMGAPI for this:
   <https://github.com/joyent/sdc-imgapi/commit/7d0b4b7dedc7c36ba1eec23394d009567b6ef35a>

4. To test your changes, one way is to use Jenkins' `TRY_BRANCH` builds:

    (a) Push your changes to a feature branch (of MG and your repo, say,
        sdc-cnapi.git)
    (b) Make a `TRY_BRANCH=<feature branch name>` build in Jenkins.
    (c) Update your COAL to that image, e.g.: `sdcadm up -C experimental cnapi`
    (d) Or possibly build a COAL with your image, by adding something like this
        to `build.spec.local` in your sdc-headnode.git clone:

        ```
        "zones": {
            "cnapi": {
                "source": "manta",
{'fraction_non_alphanumeric': 0.08744076986957158, 'fraction_numerical': 0.049338088026964974, 'mean_word_length': 3.164361269324654, 'pattern_counts': {'":': 14, '<': 39, '<?xml version=': 0, '>': 53, 'https://': 14, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3348743', 'n_tokens_mistral': 7358, 'n_tokens_neox': 6692, 'n_words': 2785}