Skip to main content
Runbooks

What You’ll Accomplish

Runbooks let you create reusable templates for common operations. Instead of typing the same queries or commands repeatedly, you can:
  • Create parameterized templates stored in Git
  • Share approved procedures across your team
  • Enforce input validation and safe defaults
  • Maintain an audit trail of every execution

How It Works

1

Create Template

Write a runbook template with placeholders for parameters
2

Store in Git

Commit the template to your Git repository
3

Configure Hoop

Point Hoop to your repository
4

Execute

Users select the runbook, fill in parameters, and run

Example Workflow

  1. DBA creates a runbook for looking up customer data
  2. Template stored in runbooks/customer-lookup.runbook.sql
  3. Support team selects the runbook, enters customer ID
  4. Query executes with proper validation and audit logging

Quick Start

Prerequisites

To get the most out of this guide, you will need to:
  • A Git repository for storing runbooks
  • Git access credentials (SSH key or token)

Step 1: Create a Runbook File

Create a file in your repository with the .runbook.<ext> extension: runbooks/customer-lookup.runbook.sql
SELECT customer_id, name, email, created_at
FROM customers
WHERE customer_id = {{ .customer_id
    | description "Customer ID to look up"
    | required "Customer ID is required"
    | type "number" }}

Step 2: Configure Git Integration

In the Web App:
  1. Go to Manage > Runbooks
  2. Click Configure Repository
  3. Enter your repository URL and credentials
Or via CLI:
hoop admin create plugin runbooks \
  -c GIT_URL=git@github.com:your-org/runbooks.git \
  -c GIT_SSH_KEY=file://$HOME/.ssh/deploy_key

Step 3: Run the Runbook

  1. Go to Runbooks in the sidebar
  2. Select customer-lookup
  3. Enter the customer ID
  4. Click Execute

Template Syntax

Runbooks use Go’s text/template syntax. Parameters are defined with {{ .parameter_name }}.

Basic Parameter

SELECT * FROM orders WHERE id = {{ .order_id }}

Parameter with Validation

SELECT * FROM users
WHERE email = {{ .email
    | description "User email address"
    | required "Email is required"
    | pattern "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" }}

Parameter Functions

FunctionDescriptionExample
descriptionHelp text for the inputdescription "Customer ID"
requiredError message if emptyrequired "This field is required"
defaultDefault value if not provideddefault "US"
typeInput type for UItype "number"
patternRegex validationpattern "^[0-9]+$"
optionsDropdown optionsoptions "active" "inactive"
squoteWrap value in single quotessquote
dquoteWrap value in double quotesdquote

Input Types

TypeUI Behavior
textStandard text input
numberNumeric input
emailEmail validation
dateDate picker
timeTime picker
selectDropdown (use with options)

Example Runbooks

SQL: Customer Lookup

-- runbooks/sql/customer-lookup.runbook.sql
SELECT
    customer_id,
    name,
    email,
    status,
    created_at
FROM customers
WHERE customer_id = {{ .customer_id
    | description "Customer ID"
    | required "Customer ID is required"
    | type "number"
    | squote }}

SQL: Update Order Status

-- runbooks/sql/update-order-status.runbook.sql
UPDATE orders
SET
    status = {{ .new_status
        | description "New order status"
        | type "select"
        | options "pending" "processing" "shipped" "delivered"
        | required "Status is required"
        | squote }},
    updated_at = NOW()
WHERE order_id = {{ .order_id
    | description "Order ID to update"
    | required "Order ID is required"
    | type "number" }}

Bash: Service Restart

# runbooks/ops/restart-service.runbook.sh
#!/bin/bash
SERVICE_NAME={{ .service
    | description "Service to restart"
    | type "select"
    | options "nginx" "postgres" "redis" "myapp"
    | required "Service name is required" }}

echo "Restarting $SERVICE_NAME..."
sudo systemctl restart $SERVICE_NAME
sudo systemctl status $SERVICE_NAME

Python: Data Export

# runbooks/data/export-report.runbook.py
# {{ .start_date | description "Start date (YYYY-MM-DD)" | required "Start date required" | asenv "START_DATE" }}
# {{ .end_date | description "End date (YYYY-MM-DD)" | required "End date required" | asenv "END_DATE" }}
# {{ .format | description "Export format" | type "select" | options "csv" "json" | default "csv" | asenv "FORMAT" }}

import os
import pandas as pd

start = os.environ['START_DATE']
end = os.environ['END_DATE']
fmt = os.environ['FORMAT']

# Your export logic here
print(f"Exporting data from {start} to {end} as {fmt}")

Kubernetes: Scale Deployment

# runbooks/k8s/scale-deployment.runbook.sh
# {{ .namespace | description "Kubernetes namespace" | default "default" | asenv "NAMESPACE" }}
# {{ .deployment | description "Deployment name" | required "Deployment required" | asenv "DEPLOYMENT" }}
# {{ .replicas | description "Number of replicas" | type "number" | required "Replicas required" | asenv "REPLICAS" }}

kubectl scale deployment/$DEPLOYMENT \
    --replicas=$REPLICAS \
    --namespace=$NAMESPACE

kubectl rollout status deployment/$DEPLOYMENT --namespace=$NAMESPACE

Security Features

Input Validation

Use pattern to prevent injection attacks:
-- Safe: Only allows numeric IDs
WHERE id = {{ .id | pattern "^[0-9]+$" }}

-- Unsafe: Allows any input (SQL injection risk)
WHERE id = {{ .id }}

Environment Variables

Use asenv to pass values as environment variables instead of inline:
# {{ .password | asenv "DB_PASSWORD" }}
psql -h localhost -U admin -c "SELECT 1"
# Password passed via PGPASSWORD, not visible in command

Quoting

Use squote or dquote to properly quote string values:
WHERE name = {{ .name | squote }}
-- Produces: WHERE name = 'John'

File Organization

Recommended repository structure:
runbooks/
├── sql/
│   ├── customer-lookup.runbook.sql
│   ├── order-update.runbook.sql
│   └── report-generation.runbook.sql
├── ops/
│   ├── restart-service.runbook.sh
│   ├── check-logs.runbook.sh
│   └── deploy.runbook.sh
├── k8s/
│   ├── scale-deployment.runbook.sh
│   └── rollback.runbook.sh
└── data/
    ├── export-report.runbook.py
    └── cleanup-old-data.runbook.sql

Naming Convention

Files must end with .runbook.<extension>:
  • .runbook.sql - SQL queries
  • .runbook.sh - Bash scripts
  • .runbook.py - Python scripts
  • .runbook.rb - Ruby scripts

Integration with Other Features

FeatureHow It Works with Runbooks
Access RequestsRunbook execution can require approval
GuardrailsRules apply to runbook-generated queries
Live Data MaskingResults are masked automatically
Session RecordingAll executions are recorded
Parallel ModeRun runbooks across multiple connections

Troubleshooting

Runbook Not Appearing

Check:
  1. File ends with .runbook.<ext>
  2. Git repository is configured correctly
  3. Hoop can access the repository (check credentials)
  4. Run hoop admin get runbooks to verify sync

Template Parsing Error

Check:
  1. All {{ }} brackets are balanced
  2. Function names are spelled correctly
  3. Pipes | are used correctly
Test locally:
hoop runbooks lint path/to/your.runbook.sql

Parameter Validation Failing

If a parameter fails validation:
  1. Check the pattern regex is correct
  2. Test the regex at regex101.com
  3. Ensure required values are provided

Best Practices

Validate Inputs

Always use pattern for user inputs to prevent injection

Add Descriptions

Every parameter should have a clear description

Set Defaults

Provide sensible defaults where appropriate

Version Control

Store runbooks in Git for history and review

Next Steps