Deploy Node.js servers using deployment REST APIs


Overview

We can deploy Node.js applications as members of a collective using the DeployService REST APIs. A Node.js collective member is called a Node.js server in this documentation.

Stabilized feature: Managing Node.js processes using Liberty collectives is stabilized. V8 is the final supported Node.js version for Liberty collective members.

Determine the target hosts onto which we want to install Node.js servers.

Install Node.js V4. Liberty supports Node versions 4.x and 6.x.

Install the apiconnect-collective-member npm package on the target hosts.

    npm install -g apiconnect-collective-member

From the Node.js installation directory ensure we have a supported Node version...

    /path/to/nodejs> node --version v4.7.3

Each target host needs RXA or SSH.


Deploy a node.js server

  1. Add a collectiveController element to server.xml of the controller...

  2. Add the scalingController feature in the server.xml file of the controller.

    The scalingController feature is required for Node.js servers that are part of a collective.

    Enabling the scalingController feature will also enable auto-scaling behavior. If auto-scaling is not needed, disable this behavior by adding the following to the server xml file of the controller.

  3. Add a Node.js application to the collective controller.

    1. Select a Node.js application to install. The application must have its dependencies resolved. We will deploy to Liberty a node application compressed TAR archive with the .tgz extension. The application typically has the following directory structure:

        package/
              app.js
              package.json
              node_modules/.. 
              server.json

      • app.js is the application.
      • package.json has dependencies for the application, as required by the Node.js npm.
      • node_modules/.. directories provide includes used by the application, generated from package.json.
      • server.json is an optional file that configures ports and other settings.

      For application deployment info, see the wlpn-server pack command

    2. Make the Node.js application available to the controller.

      Complete either of the following actions:

      • Put the Node.js application in one of the default readDir directories, which include ${wlp.install.dir}, ${wlp.user.dir}, and ${server.output.dir}, or in a subdirectory of a default readDir directory.

      • Add to the controller server.xml file a remoteFileAccess statement that points to the location of the Node.js application. The first readDir statement provides the location of the Node.js application. This directory is the applicationDir input variable specified for the deployService deployment in step 6. The applicationDir directory is on the controller. The next three readDir statements re-enable the default readDir directories; for example:

          <remoteFileAccess>
             <readDir>/tmp/nodejsApplications</readDir>
             <!-- The following statements are required to re-enable the default readDir directories. -->
             <readDir>${wlp.install.dir}</readDir>
             <readDir>${wlp.user.dir}</readDir>
             <readDir>${server.output.dir}</readDir>
          </remoteFileAccess>

  4. Ensure that the controller server.xml file has statements that define deployment variables; for example:

    The deployment variables must set values that enable each member to have a unique port number on the target hosts.

  5. Register the host on which we want to install a Node.js server with the collective controller.

    Registering a host enables the collective controller to access files, commands, and other resources on the host. Use the wlpn-collective registerHost command to register the target host. If a host is already registered, we can use the updateHost command to reset registration information.

    Important: Run the wlpn-collective registerHost or updateHost command as the user that we will later use to deploy the member server. For example, if we run the command as the root user and then later deploy a member as a different user, the deployment fails because DeployService does not have rights to push a file to the /root/wlpn directory.

    Look at the server.xml file of the controller to find the values for the command --host, --port, --user, and --password parameters. To not use an SSH private key file, such as for target hosts on Linux or Windows operating systems, include an operating system login user and password by setting --rpcUser and --rpcUserPassword parameters. The user specified by --rpcUser must have operating system rights to the target deployment location. Ensure that the command includes --autoAcceptCertificates.

       wlpn-collective registerHost targetHost
          --host=controllerHost
          --port=controllerHTTPSPort 
          --user=controllerAdmin
          --password=controllerAdminPassword
          --rpcUser=targetHostOSUser
          --rpcUserPassword=targetHostOSUserPassword
          --autoAcceptCertificates

  6. Review the available deployment rules.

    1. Use a REST API Client to invoke a REST API that returns the available deployment rules in JSON structure.

        GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/rule

      The invocation returns the deployment rules in JSON structure; for example:

      {"rules":
      [
      {"rules":[
      {"id":"Node.js Server Rule","description":"Deploy rule for Node.js servers.","type":"Node.js",
      "deployCommands":"curl https://${wlp.admin.host}:${wlp.admin.port}/IBMJMXConnectorREST/file/${applicationDir}%2F${applicationPackage}
      --user ${wlp.admin.user}:${wlp.admin.password} -k
      --create-dirs -o ${WLPN_USER_DIR}/${serverName}/${applicationPackage}
      --verbose && ${NODE_BIN}
      ${WLPN_INSTALL_DIR}/wlpn-server unpack ${serverName}
      ${WLPN_USER_DIR}/${serverName}/${applicationPackage} && ${NODE_BIN}
      ${WLPN_INSTALL_DIR}/wlpn-collective join ${serverName}
      --host=${wlp.admin.host}
      --port=${wlp.admin.port}
      --user=${wlp.admin.user}
      --password=${wlp.admin.password}
      --keystorePassword=${keystorePassword}
      --hostName=${wlp.deploy.host}
      --clusterName=${clusterName}
      --genDeployVars
      --autoAcceptCertificates",
      "undeployCommands":"${NODE_BIN} ${WLPN_INSTALL_DIR}/wlpn-server stop ${serverName};
      ${NODE_BIN} ${WLPN_INSTALL_DIR}/wlpn-collective remove ${serverName}
      --host=${wlp.admin.host}
      --port=${wlp.admin.port}
      --user=${wlp.admin.user}
      --password=${wlp.admin.password}
      --autoAcceptCertificates
      --hostName=${wlp.deploy.host}",
      "startCommands": "${NODE_BIN} ${WLPN_INSTALL_DIR}/wlpn-server start ${serverName}",
      "stopCommands":"${NODE_BIN} ${WLPN_INSTALL_DIR}/wlpn-server stop ${serverName}",
      "restartCommands":"${NODE_BIN} ${WLPN_INSTALL_DIR}/wlpn-server stop ${serverName} &&
      ${NODE_BIN} ${WLPN_INSTALL_DIR}/wlpn-server start ${serverName}", "inputVariables":[
      {"name":"applicationPackage","type":"file","description":"Application package (.tgz) to install.","displayName":"Server Package File"},
      {"name":"keystorePassword","type":"password","description":"Password for keystores of the deployed server","displayName":"Keystore Password"},
      {"name":"serverName","type":"String","description":"Name of the server to run the application.","displayName":"Server Name"},
      {"name":"applicationDir","type":"filePath","description":"Location of directory containing the application to deploy.","displayName":"Application Directory"},
      {"name":"clusterName","type":"String","description":"Name of the Liberty Node.js cluster.","displayName":"Cluster Name"}
      ],
      "name":"Node.js Server","default":true,"runtimeTypes":[{"displayName":"Node.js"}],"packageType":"Application Package" ]}

    2. If necessary, create our own deployment rules by adding DeployRules to your controller configuration.

  7. Deploy the Node.js server.

    Use a tool that can invoke REST APIs to deploy the Node.js server. The deployment rule contains variables that can specify input values for the invocation, such as theNode.js server to use and the container name to create. The return body contains a token used to request status and results.

      POST https://controller_host:controller_port/ibm/api/collective/v1/deployment/deploy
      
      {    
         "rule":"Node.js Server Rule",
         "hosts":["localhost"],
         "variables": [
            { "name":"applicationPackage","value":"express-example-app-1.0.2.tgz" },
            { "name":"serverName","value":"ds-member-ctrl5" },
            { "name":"clusterName","value":"MyCluster" },
            { "name":"keystorePassword","value":"password" },
            { "name":"applicationDir","value":"%2Ftmp%2FnodejsApplications" }
         ]
      }
      

    Attention: The applicationDir variable is a UTF-8 encoded directory path. The applicationDir variable is the location of the Node.js application on the collective controller.

    Use the return token, which might resemble {"id":3}, to get status and results. We can get the output in JSON format.


What to do next

Request and review the deployment status and results.

  • Get a list of deployment tokens for requested deployment operations.

      GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/deploy

  • Get a short status of the deployment operations. Use the token from Deploy the Node.js server for {token}. Thus, for a {"id":3} return token use 3 for {token}.

      GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/{token}/status

    During deployment, the API returns IN_PROGRESS:

      {"status":{"target_host":"IN_PROGRESS"}}

    After deployment, the API returns FINISHED:

      {"status":{"target_host":"FINISHED"}}

    You can also get a final status of ERROR if the deployment has problems. Use the following information to get the complete results. The stdout and stderr information that is returned can help you diagnose the problems.

  • Get the complete results of a deployment operation. Use the token from Deploy the Node.js server for {token}. Thus, for a {"id":3} return token use 3 for {token}.

      GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/{token}/results

    After deployment completes, the results contain information about the operation. The following example shows results for FINISHED:

      {"results":[{"host_name":"target_host","status":"FINISHED","result":0,"stdout":"deployment_stdout", "stderr":"deployment_stderr", "deployedArtifactName":"serverName_from_inputVars", "deployedUserDir":"target_host_directory_for_deployed_server"}]}

Undeploy the Node.js server. We do not need to specify a deploy rule. The rule used for deployment was stored at deploy time. We can use the rule for undeployment. The server tuple of host name, user directory, and server name is used to undeploy the server. This tuple is shown on server pages in the Explore tool of Admin Center.

  • Undeploy a Node.js server.

      POST https://controller_host:controller_port/ibm/api/collective/v1/deployment/undeploy
      {     
         "host": "myHostName",
         "userDir":"/root/wlpn",     
         "serverName":"myServerName"
      }

  • Get a list of tokens for undeployment operations.

      GET https://controller_host:controller_port/ibm/api/collective/v1/deployment/undeploy

    To get status and results, follow steps similar to deployments.


Related reference