For LINUX platformsFor Windows platforms

Deploying Node.js servers using deployment REST APIs

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

Before you begin

Stabilized feature: Managing Node.js processes by using Liberty collectives is stabilized. V8 is the final supported Node.js version for Liberty collective members. For on-premises or bring-your-own infrastructure environments, use Docker containers that are hosted and managed by IBM Cloud® Private. For hosted environments, use Docker containers in IBM Cloud Kubernetes Service.

Determine the target hosts onto which you want to install Node.js servers. Install Node.js V4 and the apiconnect-collective-member npm package on the target hosts. The command to install support for Node.js servers on Linux is:

npm install -g apiconnect-collective-member

Liberty supports Node versions 4.x and 6.x.

After installing Node.js, run node --version from a command line at the Node.js installation directory to ensure you have a supported Node version; for example:

C:\nodejs>node --version
v4.7.3

Each target host needs RXA or SSH. See Setting up RXA for Liberty collective operations.

Procedure

  1. To record a user and password for the controller host, add a collectiveController element to the server.xml file of the controller, for example:
    <collectiveController user="admin" password="adminpwd" />
  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.
        <featureManager>
    	 ...
            <feature>scalingController-1.0</feature>
        </featureManager>
    Attention: 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.
      <scalingDefinitions>
        <defaultScalingPolicy enabled="false"/>
      </scalingDefinitions>
  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.
      You 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 more information about the application to deploy, see the pack command description in apiconnect-collective-member wlpn-server and wlpn-collective commands.

    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 that is 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:
       <deployVariable name="wlpn.appPort" value="9090" increment="1"/> 
       <deployVariable name="wlpn.adminPort" value="9453" increment="1"/>

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

  5. Register the host on which you 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, you can use the updateHost command to reset registration information.

    Important: Ensure you run the wlpn-collective registerHost or updateHost command as the user that you will later use to deploy the member server. For example, if you 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

    For more information, see apiconnect-collective-member wlpn-server and wlpn-collective commands.

  6. Review the available deployment rules.
    1. Invoke a REST API that returns the available deployment rules in JSON structure.
      Use a tool that can invoke REST APIs to get the available deployment rules.
      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":"Name of the 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 your own deployment rules by adding DeployRules to your controller configuration. See Deploy Rule (deployRule.
  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 that you can use 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. You 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 step 6 for {token}. Thus, for a {"id":3} return token from step 6, 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 step 6 for {token}. Thus, for a {"id":3} return token from step 6, 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. You do not need to specify a deploy rule. The rule used for deployment was stored at deploy time. You 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.