Creating Semantic Pipeline Rules

This tutorial demonstrates how to implement semantic pipeline rules, including:

No delete hook example

The No delete hook is an example event handler written as a Node.js application. The no delete hook is prevents any app from performing DELETE or DROP commands against a Postgres database. The DB is named db123 in this example.

  1. Create a new directory, e.g. sp-hook-no-delete, and cd into it.

  2. Write your hook application in a file called app.js:

    var express = require('express');
    var app = express();
    app.use(express.bodyParser());
    
    app.post('/auth', function(req, res) {
      if (req.body.Command.match(/DROP/i) || req.body.Command.match(/DELETE/i)) {
        // reject all drop and delete commands
        res.json({ Permitted: false, Reason: "No!" });
      } else {
        // permit anything else
        res.json({ Permitted: true, Reason: "Move along" });
      }
    });
    
    // get the port from environment, or default to 4000
    var port = process.env.PORT || 4000
    app.listen(port);
    
    // put a friendly message on the terminal
    console.log("Server running at http://127.0.0.1:"+port+"/");
    
  3. Declare dependencies in a file called package.json in the sp-hook-no-delete directory:

    {
      "name": "no-delete",
      "version": "0.0.1",
      "scripts": {
        "start": "node ./app.js"
      },
      "dependencies": {
        "express": "3.x"
      }
    }
    
  4. Deploy the hook to Apcera:

    $ apc app create nodelete --start
    Deploy path [~/sp-hook-no-delete]:
    Memory [256]:
    ...
    Is this correct? [Y/n]: y
    Looking up staging pipeline 'nodejs'
    Found pipeline nodejs with UUID d15c2962-fc86-492d-910a-d870dacc6941
    Packaging... done
    Uploading package... done
    [STAGING] Subscribing to the staging process...
    [STAGING] Beginning staging with 'stagpipe::/apcera::nodejs' pipeline, 1 stager(s)  defined.
    [STAGING] Launching instance of stager 'nodejs'...
    [STAGING] Launching instance of stager 'nodejs'...
    Creating the application "nodelete"... done
    Waiting for the application to start...
    App should be accessible at "http://nodelete.yourcluster.example.com"
    Success!
    
  5. Create a Rule to invoke the hook on any database services created from the /apcera/providers::postgres-provider provider:

    $ apc rule create denydelete --provider /apcera/providers::postgres-provider --type=hook --url=http://nodelete.yourcluster.example.com/auth
    
    Event Rule Creation Settings
    Rule Name:denydelete
    Provider Name:/apcera/providers::postgres-provider
    Event Type:hook
    Event URL:http://nodelete.yourcluster.example.com/auth
    Is this correct? [Y/n]: y
    Finding semantic pipeline... done, found SP for service "db123"
    Updating SP event rules... done
    Success!
    

Latency hook example

The latency hook is an example event handler. The latency hook is written as a Node.js application. The latency hook randomly injects latency into an app connecting to a Postgres database named db123.

  1. Create a new directory called sp-hook-latency, and cdinto it.

  2. Write your hook application in a file called app.js:

    var express = require('express');
    var app = express();
    app.use(express.bodyParser());
    
    app.get('/slow', function(req, res) { res.json({alive: "true"}) });
    app.post('/slow', function(req, res) {
      // pick a random amount of time between 100ms and 1s
      latency = Math.floor(Math.random() * 900) + 100;
      setTimeout(function() {
        res.json({ Permitted: true, Reason: "Move along" })
      }, latency);
    });
    
    // get the port from environment, or default to 4000
    var port = process.env.PORT || 4000
    app.listen(port);
    
    // put a friendly message on the terminal
    console.log("Server running at http://127.0.0.1:"+port+"/");
    
  3. Declare dependencies in a file called package.json in the sp-hook-latency directory:

    {
    
      "name": "latency-hook",
      "version": "0.0.1",
      "scripts": {
        "start": "node ./app.js"
      },
      "dependencies": {
        "express": "3.x"
      }
    }
    
  4. Deploy the hook to Apcera:

    $ apc app create latency-monkey --start
    Deploy path [~/sp-hook-latency]:
    Memory [256]:
    ...
    Is this correct? [Y/n]: y
    Looking up staging pipeline 'nodejs'
    Found pipeline nodejs with UUID d15c2962-fc86-492d-910a-d870dacc6941
    Packaging... done
    Uploading package... done
    [STAGING] Subscribing to the staging process...
    [STAGING] Beginning staging with 'stagpipe::/apcera::nodejs' pipeline, 1 stager(s)  defined.
    [STAGING] Launching instance of stager 'nodejs'...
    [STAGING] Launching instance of stager 'nodejs'...
    Creating the application "latency-monkey"… done
    Waiting for the application to start...
    App should be accessible at "http://latency-monkey.yourcluster.example.com"
    Success!
    
  5. Create a rule to invoke the hook on the db123 database service:

    $ apc rule create addlatency --service db123 -t hook --commands=select --url=http://latency-monkey.yourcluster.example.com/slow
    
    Event Rule Creation Settings
    Rule Name:addlatency
    Service Name:db123
    Event Type:hook
    Event URL:http://latency-monkey.yourcluster.example.com/slow
    Command List:select
    Is this correct? [Y/n]: y
    Finding semantic pipeline... done, found SP for service "db123"
    Updating SP event rules... done
    Success!