Creating and Using a Custom Package

This tutorial shows how to create an Apcera package from a third-party Node module and then use the package in an application. For this tutorial you will create a package for Node-RED a Node module that provide a visual tool for wiring together devices, APIs and services.

Create the Node-RED package

To create a package you use a package script, which contains metadata about the package, and a build script block. Metadata includes the package name and version, any dependencies it requires or provides that it can satisfy, and any environment variables to set on the package. The build script block contains Bash commands that perform any additional tasks to prepare the package to run.

To create the Node-RED package:

  1. In a new project folder create a package script file named node-red.conf with the following text:

     name:       "node-red-0.16.2"
    
     build_depends [ { package: "build-essential" },
                     { runtime: "node" } ]
     depends       [ { os: "linux" },
                     { runtime: "node" } ]
     provides      [ { package: "node-red" },
                     { package: "node-red-0.16" },
                     { package: "node-red-0.16.2" } ]
     environment {   "PATH": "$PATH:/usr/local/bin",
                     "NODERED_HOME": "/opt/node-red/node_modules/node-red" }
     build (
         export INSTALLPATH=/opt/node-red
         (
             mkdir -p $INSTALLPATH
             cd $INSTALLPATH
             npm install node-red@0.16.2
         )
     )
    

    Let's examine the contents of this script:

    • name specifies the package's name. By convention, the package version is appended to the name.
    • build_depends specifies the dependencies required to build the package. In this case, it depends on Node and the build-essential package that's provided with Apcera to assist with build tasks. These packages are removed once the build has finished.
    • depends specifies the dependencies required to run the package; in this case it requires Linux and Node.
    • provides specifies the capabilities that the package can provide to other packages.
    • environment specifies environment variables to set on the package's environment. In this case, we append /usr/local/bin to the existing PATH variable and set a variable named NODERED_HOME to the location where the node-red module is installed. The application you'll create next uses this environment variable to call the correct start command.
    • The build property is a block of bash statements delineated by a pair of parentheses. In this case, the build script creates a folder to install the module, changes to that directory and runs npm install. The closing parenthesis must be the first and only character of the final line of the block.
  2. Save your changes to node-red.conf and run the following command:

     apc package build node-red.conf --batch
     ...
     [staging] Staging is complete.
    
     Built "package::/sandbox/admin::node-red-0.16.2"
     Success!
    

    When the build process has completed successfully you should see a Success! message indicating that the package was created.

    Note that the package's namespace ("/sandbox/admin" in this case) may be different for your environment.

Create an Application from the Package

Next you'll create an application that uses the Node-RED package you just created. To deploy the application you'll use a multi-resource manifest, a JSON file that defines the jobs to create and their deployment attributes. The main benefit of a manifest is that it provides easily reproducible application deployment settings.

To create an application from the Node-RED package:

  1. Create a file named node-red-app.json and add the following JSON to it:

     {
       "jobs": {
         "job::${NAMESPACE}::node-red-app": {
           "packages": [
             {
               "fqn": "package::/sandbox/admin::node-red-0.16.2"
             }
           ],
           "exposed_ports": [
             1880
           ],
           "routes": [
             {
               "type": "http",
               "endpoint": "auto",
               "config": {
                 "/": [
                   {
                     "port": 1880
                   }
                 ]
               }
             }
           ],
           "start": {
             "cmd": "sudo node $NODERED_HOME/red.js"
           },
           "state": "started"
         }
       }
     }
    

    Note the following about the manifest:

    • The app's FQN ("job::${NAMESPACE}::node-red-app") includes a substitution variable named ${NAMESPACE}, rather than hard-coding the app's namespace. During manifest deployment this variable resolves to the current default namespace set by APC, making the manifest more portable.
    • The packages field lists the FQN (fully-qualified name) of the package(s) the app needs to run, which in this case is just the Node-RED package you created.
    • The exposed_ports field specifies the port(s) where the application is listening. By default, the Node-RED module serves its UI on port 1880.
    • The routes field creates an HTTP route on port 1880 with an automatically generated endpoint for the route. You can optionally assign a specific endpoint for your cluster (nodered.mycluster.example.com, for example).
    • The start field specifies the command to start the application. Note that it uses the NODERED_HOME environment variable (set by the package script) to locate the correct entry point (red.js).
    • The "state": "started" field indicates that the app should be started immediately when it's ready.
  2. Save your changes to node-red-app.json and then deploy it with the apc manifest deploy command:

     apc manifest deploy node-red-app.json
     Deploying manifest...
     Warning: no value found for variable NAMESPACE
     [manifest] -- Deploy -- execution started
     [manifest] -- Deploy -- looking up "package::/sandbox/admin::node-red-0.16.2"
     [manifest] -- Deploy -- updating "job::/sandbox/admin::node-red-app"
     [manifest] -- Finish -- execution was successful
    
    
     ╭───────────────────────────────────┬─────────┬───────────┬────────┬────────╮
     │ Job FQN                           │ Status  │ Instances │ Subnet │ Errors │
     ├───────────────────────────────────┼─────────┼───────────┼────────┼────────┤
     │ job::/sandbox/admin::node-red-app │ started │ 1         │ N/A    │        │
     ╰───────────────────────────────────┴─────────┴───────────┴────────┴────────╯
     Success!
    
  3. Run apc app show node-red-app to view the auto-generated route endpoint:

     apc app show node-red-app
     ╭──────────────────────┬──────────────────────────────────────────────────────────────────────╮
     │ Job:                 │ node-red-app                                                         │
     ├──────────────────────┼──────────────────────────────────────────────────────────────────────┤
     │ FQN:                 │ job::/sandbox/admin::node-red-app                                    │
     │ UUID:                │ cebe99b8-c035-4b5a-80b4-ec0da2707e76                                 │
     │ ....                 │ ...                                                                  │
     │                      │                                                                      │
     │ Routes:              │ http://node-red-app-tjzn2e.example.com [to port 1880] (Weight: auto) │
    

    Open the specifed URL in a web browser to see the Node-RED interface running.