How to Extend ChaosBlade with Custom Matchers and Flags: A Complete Guide
You can extend ChaosBlade with custom matchers and flags by editing YAML specification files in $HOME/.chaosblade/spec without recompiling the binary, as the CLI dynamically builds its command tree from these specs at runtime.
ChaosBlade is an open-source chaos engineering platform that uses a specification-driven architecture to define experiments. Understanding how to extend ChaosBlade with custom matchers and flags allows you to tailor resource selection and experiment parameters to your specific infrastructure needs without modifying the core Go source code.
Understanding ChaosBlade's Specification-Driven Architecture
ChaosBlade constructs its entire command-line interface from YAML specification files that describe experiments, actions, flags, and matchers. When the CLI initializes, it loads these specifications and dynamically registers commands using Cobra.
How the CLI Builds Commands from YAML
The entry point for command registration occurs in cli/cmd/exp.go. The process follows three distinct phases:
- Specification Loading: The system loads YAML files from the directory returned by
specutil.GetYamlHome()(default:$HOME/.chaosblade/spec):
models, err := specutil.ParseSpecsToModel(file, os.NewExecutor())
// cli/cmd/exp.go: 38-42
- Command Registration: For each experiment model, the system registers a top-level command:
command := ec.registerExpCommand(model, "")
// cli/cmd/exp.go: 48-55
- Flag Binding: The system binds both action flags and matcher flags to the command:
// bind matcher flags
ec.bindFlagsFunc(command.MatcherFlags, command.command, actionCommandSpec.Matchers())
// cli/cmd/exp.go: 400-402
The Role of Matchers and Flags
In ChaosBlade's architecture, matchers function as specialized flags used for resource selection (such as --process or --container), while flags define experiment parameters (such as --time or --duration). Both follow the same ExpFlagSpec schema defined in the chaosblade-spec-go library, but matchers are processed separately to facilitate resource targeting.
Adding Custom Matchers to ChaosBlade Experiments
Extending ChaosBlade with custom matchers requires creating or modifying YAML specification files. This approach requires no recompilation of the binary.
Creating or Editing YAML Specification Files
Create a new YAML file or edit an existing spec in $HOME/.chaosblade/spec/. The filename typically follows the pattern chaosblade-<target>-spec-<version>.yaml.
For example, to add a custom matcher for process selection:
# $HOME/.chaosblade/spec/chaosblade-os-spec-1.9.0.yaml
- name: process
scope: host
actions:
- name: kill
flags:
- name: signal
desc: signal to send (default: SIGKILL)
matchers:
- name: process
desc: name of the process to kill
required: true
- name: mylabel
desc: custom label matcher for process selection
required: false
Defining Matcher Properties
Matchers support the same properties as standard flags:
- name: The flag name used on the CLI (e.g.,
--mylabel) - desc: Description shown in help text
- required: Boolean indicating if the matcher must be provided
- default: Optional default value
Using Custom Matchers in Commands
After saving the YAML file, the CLI automatically discovers the new matcher. Execute the experiment using your custom matcher:
cb create process kill --mylabel myapp-tier --signal SIGTERM
The matcher value is passed to the executor via expModel.ActionFlags["mylabel"], as implemented in exec/os/executor.go at line 313 within the convertFlagsToResourceFlags function.
Implementing Custom Flags for Experiment Actions
Custom flags follow the same YAML-based approach as matchers but are declared under the flags section rather than matchers.
Declaring Action-Level Flags
Add flags to any action in your YAML specification:
- name: network
scope: host
actions:
- name: delay
flags:
- name: time
desc: delay time in ms
required: true
- name: duration
desc: how long the delay lasts (seconds)
required: false
- name: jitter
desc: network jitter in ms
required: false
These flags become standard Cobra command-line flags accessible via --time, --duration, and --jitter.
Accessing Flag Values in Executors
When the experiment executes, flag values are available in the ExpModel structure:
// Inside your executor implementation
func (e *executor) Exec(expModel *spec.ExpModel) (*spec.Response, error) {
delayTime := expModel.ActionFlags["time"]
duration := expModel.ActionFlags["duration"]
// Implementation logic using these values
}
Advanced: Creating Custom Executors for Complex Matchers
When custom matchers require specialized processing logic beyond standard resource selection, implement a custom spec.Executor.
Implementing the spec.Executor Interface
Create a new executor struct that implements the interface defined in the chaosblade-spec-go library:
package myexecutor
import (
"github.com/chaosblade-io/chaosblade-spec-go/spec"
)
type customExecutor struct{}
// Exec implements spec.Executor
func (e *customExecutor) Exec(expModel *spec.ExpModel) (*spec.Response, error) {
// Retrieve custom matcher values
customMatcher := expModel.ActionFlags["mylabel"]
// Implement custom resource selection logic
// Return spec.Response with success or failure details
return spec.Success(), nil
}
// SetChannel implements spec.Executor (required for some implementations)
func (e *customExecutor) SetChannel(channel spec.Channel) {}
Registering Your Executor
Register the executor in the appropriate register*ExpCommands function within cli/cmd/exp.go:
// In your command registration logic
executors[createExecutorKey("mytarget", "host", "myaction")] = &myexecutor.customExecutor{}
This registration pattern follows the existing implementation at line 69 of cli/cmd/exp.go where executors are mapped to specific target-scope-action combinations.
Key Source Files and Implementation Details
Understanding these specific source files helps when debugging or extending ChaosBlade:
| File | Purpose | Key Lines |
|---|---|---|
cli/cmd/exp.go |
Core command registration and flag binding | 38-42 (spec loading), 48-55 (command registration), 400-402 (matcher binding) |
cli/cmd/check_os.go |
Demonstrates matcher and flag merging logic | mergeMatchesAndFlags function |
exec/os/executor.go |
Consumes matcher values during execution | 313 (convertFlagsToResourceFlags) |
build/spec/spec.go |
Programmatic spec generation | 168-172 (ActionMatchers field) |
spec/util/parse.go |
YAML parsing into Go structs | External library: chaosblade-spec-go |
spec/exp_flag.go |
Flag and matcher schema definition | External library: chaosblade-spec-go |
Summary
- ChaosBlade uses YAML specifications located in
$HOME/.chaosblade/specto dynamically build its CLI, eliminating the need for recompilation when adding matchers or flags. - Custom matchers are defined under the
matchers:section in action specifications and function as specialized resource selectors passed to executors viaexpModel.ActionFlags. - Custom flags follow the same YAML schema as matchers but reside under
flags:and define experiment parameters rather than resource selection criteria. - Implementation details center on
cli/cmd/exp.gofor command registration (lines 400-402 for matcher binding) andexec/os/executor.gofor flag consumption at runtime. - Advanced extensions require implementing the
spec.Executorinterface and registering the executor in the command initialization map for custom processing logic.
Frequently Asked Questions
Do I need to recompile ChaosBlade to add custom matchers?
No, you do not need to recompile the binary. ChaosBlade loads experiment specifications from YAML files in $HOME/.chaosblade/spec at runtime. Simply create or edit a spec file, add your matcher under the matchers: section of the desired action, and the CLI will automatically expose it as a new flag.
What is the difference between a matcher and a flag in ChaosBlade?
While both use the same underlying ExpFlagSpec schema, matchers are specialized flags used for resource selection (such as --process or --container) and are processed separately to identify target resources. Flags define experiment parameters (such as --duration or --time) that control how the action behaves. Matchers are defined under matchers: in the YAML, while flags are defined under flags:.
How do I access custom matcher values in my experiment executor?
Custom matcher values are accessible via the ActionFlags map in the ExpModel struct passed to your executor's Exec method. For example, if you defined a matcher named mylabel, you retrieve it in Go code using expModel.ActionFlags["mylabel"]. The executor at exec/os/executor.go demonstrates this pattern in the convertFlagsToResourceFlags function around line 313.
Can I add custom matchers to existing ChaosBlade experiments like network or CPU?
Yes, you can extend existing experiments by modifying their specification files. Locate the YAML spec for the target (such as chaosblade-os-spec.yaml for OS-level experiments), find the action you want to extend (like delay for network or fullload for CPU), and add your custom matcher under the matchers: section. The ChaosBlade CLI will automatically merge your custom matcher with the existing command structure when it parses the specification on startup.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →