Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dst

Deterministic Simulation Testing for containerised services.

Write Lua scripts to define, control, and verify chaos experiments on Docker containers with reproducible fault injection.

Overview

dst lets you write Lua scripts that define test subjects (Docker containers), inject faults (pause, kill, resource deprivation), and verify service resilience. All experiments are deterministic when seeded, making them reproducible across runs.

Installation

cargo install --path .

Or build from source:

cargo build --release

Quick Start

cat examples/basic.lua | cargo run

Lua API

Core Functions

dst.seed(n)

Sets the random seed for deterministic fault selection. Must be called before dst.step() or dst.run_steps() when require_seed is true (default).

dst.seed(42)

dst.setup(type, config)

Creates a test subject container. Returns a subject ID string in the format docker/<container-id>.

local subject = dst.setup("docker", {
    image = "kennethreitz/httpbin",
    ports = { 80 },
})

dst.http(subject, method, path)

Makes an HTTP request to a subject. Returns a table with status and body.

local resp = dst.http(subject, "GET", "/get")
assert(resp.status == 200)

dst.opts(config)

Configures experiment behavior. Call before dst.step() or dst.run_steps().

dst.opts({
    weights = {pause = 0.5, kill = 0.3, ["deprive:disk"] = 0.2},
    accumulation = "single",
    http_timeout = 10,
})

Fault Injection

dst.step()

Applies the next fault in the sequence. Returns a table describing what happened, or {more = false} when complete.

while true do
    local result = dst.step()
    if not result.more then
        break
    end
    -- Verify service still works
    local resp = dst.http(subject, "GET", "/get")
    dst.info("status=" .. resp.status .. " after fault=" .. result.fault)
end

Return table fields:

  • fault (string): The fault type applied
  • subject (string): The subject ID (format: docker/<container-id>)
  • round (number): Current round number (1-indexed)
  • total_rounds (number): Total rounds in this experiment
  • remaining (number): Steps remaining
  • more (boolean): Whether more steps are available

dst.run_steps(n)

Runs multiple steps and returns an array of results.

local results = dst.run_steps(5)
for i, result in ipairs(results) do
    dst.info("round " .. result.round .. ": " .. result.fault)
end

dst.clear(subject)

Clears all active faults on a subject.

dst.clear(subject)

Logging

  • dst.debug(msg) - Debug-level message
  • dst.info(msg) - Info-level message
  • dst.warn(msg) - Warning-level message
  • dst.error(msg) - Error-level message

Configuration

dst.opts({
    weights = {
        pause = 0.40,
        kill = 0.25,
        ["deprive:disk"] = 0.15,
        ["deprive:network"] = 0.15,
        ["deprive:memory"] = 0.05,
    },
    accumulation = "single",
    http_timeout = 5,
    http_retries = 30,
    http_retry_delay = 500,
    step_delay = 1000,
    require_seed = true,
})
Option Type Default Description
weights table See below Fault type weights for weighted random selection
accumulation string "single" Fault accumulation mode
http_timeout number 5 HTTP request timeout in seconds
http_retries number 30 HTTP retry attempts
http_retry_delay number 500 Delay between HTTP retries (ms)
step_delay number 1000 Delay before applying fault in single mode (ms)
require_seed boolean true Require dst.seed() before stepping

Default Weights

Fault Weight
pause 0.40
kill 0.25
deprive:disk 0.15
deprive:network 0.15
deprive:memory 0.05

Accumulation Modes

  • single: Each subject can have only one active fault. Previous faults are cleared before applying new ones.
  • accumulate: Multiple faults can stack on the same subject.

Fault Types

Fault Effect
pause Pauses the container (SIGSTOP)
kill Kills the container (SIGKILL)
deprive:disk Throttles disk I/O to 1KB/s
deprive:network Disconnects from bridge network (no internet)
deprive:memory Limits container memory to 4MB

Determinism

Same seed produces identical fault sequences:

dst.seed(42)
local results1 = dst.run_steps(10)

dst.seed(42)
local results2 = dst.run_steps(10)

-- results1 and results2 have identical fault sequences

Examples

  • basic.lua - Simple setup and HTTP checks
  • advanced.lua - Custom weights, stepping with verification
  • coroutine.lua - User-controlled async-style execution with Lua coroutines

Requirements

  • Docker daemon running
  • Rust 1.85+ (uses 2024 edition)

License

MIT

About

Test the **** out of containers. Deterministic chaos engineering for containerised services.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages