Create and Contribute a Pack

Packs have a defined structure that is prescribed by StackStorm. It is required to follow this structure while creating your own pack and is also helpful to know while debugging issues with packs.

Anatomy of a Pack

Canonical pack as laid out on the file system.

# contents of a pack folder
actions/                 #
rules/                   #
sensors/                 #
aliases/                 #
policies/                #
tests/                   #
etc/                     # any additional things (e.g code generators, scripts...)
config.schema.yaml       # configuration schema (replacing config.yaml)
packname.yaml.example    # example of config, used in CI
pack.yaml                # pack definition file
requirements.txt         # requirements for Python packs
requirements-tests.txt   # requirements for python tests
icon.png                 # 64x64 .png icon

Some old packs also have a configuration file at /opt/stackstorm/<pack_name>/config.yaml that defines any shared configuration used by the actions and sensors, e.g. usernames, region names, hostnames, etc. New pack rely on configuration schema and keep their configuration files under /opt/stackstorm/configs`.

At the topmost level are the main folders actions, rules, sensors, aliases and policies as well as some shared files:

  • pack.yaml - Metadata file that describes and identifies the folder as a pack.
  • config.schema.yaml - Schema that defines configuration elements used by a pack.
  • requirements.txt - File containing a list of python dependencies.
# contents of actions/
actions/
   lib/
   action1.yaml
   action1.py
   action2.yaml
   action1.sh
   workflow1.yaml
   workflow2.yaml
   workflows/
     workflow1.yaml
     workflow2.yaml

The actions folder contains action script files and action metadata files. See Actions and Workflows for specifics on writing actions. Since metadata files and workflow definitions can both be written as YAML, it’s good practice to put the workflow definitions in a separate directory. Note that the lib sub-folder is always available for access for an action script.

# contents of rules/
rules/
   rule1.yaml
   rule2.yaml

The rules folder contains rules. See Rules for specifics on writing rules.

# contents of sensors/
sensors/
   common/
   sensor1.py
   sensor1.yaml
   sensor2.py
   sensor2.yaml

The sensors folder contains sensors. See Sensors for specifics on writing sensors and registering TriggerTypes.

# contents of aliases/
aliases/
   alias1.yaml
   alias2.yaml

The aliases folder contains Action Aliases. See Action Alias for specifics on writing Action Aliases.

# contents of policies/
policies/
   policy1.yaml
   policy2.yaml

The policies folder contains Policies. See Policies for specifics on writing Policies.

Creating Your First Pack

In the example below, we will create a simple pack named hello_st2. The full example is also available at st2/contrib/hello_st2.

  1. Create the pack folder structure and related files. Let’s keep the metadata files such as pack.yaml, config.schema.yaml, and requirements.txt empty for now:
# Use the name of the pack for the folder name.
mkdir hello_st2
cd hello_st2
mkdir actions
mkdir rules
mkdir sensors
mkdir aliases
mkdir policies
touch pack.yaml
touch config.schema.yaml
touch requirements.txt

Note: All folders are optional. If a folder is present, it is inspected for content. So it is safe to skip a folder or keep it empty.

  1. Create pack definition file, pack.yaml:
---
ref: hello_st2
name: Hello StackStorm
description: A simple pack containing examples of sensor, rule, and action.
keywords:
    - example
    - test
version: 0.1.0
author: st2-dev
email: info@stackstorm.com

3. Create the action. Action consists of meta data, and entrypoint. The following example simply echoes a greeting.

Copy the following content to actions/greet.yaml:

---
name: greet
pack: hello_st2
runner_type: "local-shell-cmd"
description: Greet StackStorm!
enabled: true
entry_point: greet.sh
parameters:
    greeting:
        type: string
        description: Greeting you want to say to StackStorm (i.e. Hello, Hi, Yo, etc.)
        required: true
        position: 1

Copy the following content to actions/greet.sh:

#!/bin/bash
echo "$1, StackStorm!"
  1. Create a sensor. The sample sensor below publishes an event to StackStorm every 60 seconds.

Copy the following content to sensors/sensor1.yaml

---
class_name: "HelloSensor"
entry_point: "sensor1.py"
description: "Test sensor that emits triggers."
trigger_types:
  -
    name: "event1"
    description: "An example trigger."
    payload_schema:
      type: "object"

Copy the following content to sensors/sensor1.py

import eventlet

from st2reactor.sensor.base import Sensor


class HelloSensor(Sensor):
    def __init__(self, sensor_service, config):
        super(HelloSensor, self).__init__(sensor_service=sensor_service, config=config)
        self._logger = self.sensor_service.get_logger(name=self.__class__.__name__)
        self._stop = False

    def setup(self):
        pass

    def run(self):
        while not self._stop:
            self._logger.debug('HelloSensor dispatching trigger...')
            count = self.sensor_service.get_value('hello_st2.count') or 0
            payload = {'greeting': 'Yo, StackStorm!', 'count': int(count) + 1}
            self.sensor_service.dispatch(trigger='hello_st2.event1', payload=payload)
            self.sensor_service.set_value('hello_st2.count', payload['count'])
            eventlet.sleep(60)

    def cleanup(self):
        self._stop = True

    # Methods required for programmable sensors.
    def add_trigger(self, trigger):
        pass

    def update_trigger(self, trigger):
        pass

    def remove_trigger(self, trigger):
        pass
  1. Create a rule. The sample rule below is triggered by event from the sensor and invokes the action from the samples above.

Copy the following content to rules/rule1.yaml

---
name: on_hello_event1
pack: hello_st2
description: Sample rule firing on hello_st2.event1.
enabled: true
trigger:
    type: hello_st2.event1
action:
    ref: hello_st2.greet
    parameters:
        greeting: Yo
  1. Create an action alias. The sample action alias below aliases the greet action and makes it accessible from ChatOps.

Copy the following content to aliases/alias1.yaml

---
name: greet
pack: hello_st2
description: "Greet StackStorm"
action_ref: "hello_st2.greet"
formats:
  - "greet {{greeting}}"
  1. Create a policy. The sample policy below limits concurrent operation of the greet action.

Copy the following content to policies/policy1.yaml

---
name: greet.concurrency
pack: hello_st2
description: Limits the concurrent executions of the greet action.
enabled: true
resource_ref: hello_st2.greet
policy_type: action.concurrency
parameters:
    threshold: 10

8. Install the pack. We encourage using git, if you do so, st2 pack will greatly simplify your pack management. However you can define your own tools and workflow for editing and versioning packs; you’ll be placing the files to /opt/stackstorm/packs and [re-]loading the content.

8.1 Use git and pack install (recommended):

# Get the code under git
cd hello_st2
git init && git add ./* && git commit -m "Initial commit"
# Install from local git repo
st2 pack install file:///$PWD

When you make code changes, run st2 pack install again: it will do the upgrade. Once you push it to GitHub, you will install and update it right from there:

st2 pack install https://github.com/MY/PACK

8.2 Copy over and register (if you have special needs and know what you’re doing).

mv ./hello_st2 /opt/stackstorm/packs
st2ctl reload

Congratulate yourself: you have created your first pack. Commands like st2 pack list, st2 action list, st2 rule list and st2 trigger list will show you the loaded content. To check if the sensor triggering action is working, run st2 execution list, there should be an entry for executing hello_st2.greet every minute.

Take it from there. Write an awesome automation, or an inspiring integration pack with your favorite tool. Happy hacking!

Submitting a Pack to the Community

Now that you forged this awesome pack in StackStorm it’s time, and a good form, to share your awesomeness with the community. StackStorm Exchange is the place for you and everyone else to share and pull integration packs.

To feature your pack on the StackStorm Exchange, submit a GitHub pull request to StackStorm Exchange Incubator repository. Our team will review the PR, accept it to the incubator, graduate it to the main “Exchange”, and help you promote it.

Contributors License Agreement

By contributing you agree that these contributions are your own (or approved by your employer) and you grant a full, complete, irrevocable copyright license to all users and developers of the project, present and future, pursuant to the license of the project.


Questions? Problems? Suggestions? Engage!