ChaosBlade Prepare vs Create Commands: Key Differences Explained
The prepare command sets up the runtime environment (e.g., attaching JVM agents) without starting chaos experiments, while the create command launches actual chaos experiments (e.g., CPU load, network latency) and manages their full lifecycle.
Understanding the distinction between the prepare and create commands in the chaosblade-io/chaosblade repository is essential for effective chaos engineering workflows. While both commands interact with the internal data layer and generate unique identifiers (UIDs), they serve fundamentally different purposes in the chaos experiment lifecycle. This article examines the architectural differences, data models, and source code implementations that separate these two critical commands.
Core Purpose: Environment Setup vs Experiment Execution
The primary difference between prepare and create lies in their fundamental objectives within the chaos engineering workflow.
What the Prepare Command Does
The prepare command establishes the necessary runtime environment for future experiments without actually injecting any chaos. According to the source code in cli/cmd/prepare.go, this command handles tasks such as attaching a Java agent to a JVM process or deploying a sidecar to a Kubernetes cluster.
When executed, prepare generates a UID via util.GenerateUid() and inserts a preparation record into the database through data.GetDS().InsertPreparationRecord(). The record's status transitions from Created to Running upon successful completion of the setup logic, or to Error if the preparation fails.
What the Create Command Does
The create command launches an actual chaos experiment and manages its complete lifecycle. As implemented in cli/cmd/create.go, this command drives the execution of specific chaos actions such as CPU overload, network latency injection, or disk fill operations.
The create command builds an ExperimentModel and persists it via data.GetDS().InsertExperimentModel(). It supports both synchronous and asynchronous execution modes through the --async flag. When running asynchronously, it launches a background nohup process and immediately returns the UID, while synchronous execution blocks until the experiment completes or fails.
Data Layer: Preparation Records vs Experiment Records
Both commands interact with distinct database tables and data models, reflecting their different roles in the system.
Preparation Record Lifecycle
Preparation records are defined in data/preparation.go and track the state of environment setup operations. The PreparationRecord struct includes fields for Uid, ProgramType, ProcessName, Port, and Status.
The status lifecycle for preparation records follows this path:
Created→Running(successful setup)Created→Error(setup failure)Running→Revoked(when explicitly destroyed)
The handlePrepareResponse function in cli/cmd/prepare.go manages these transitions by calling UpdatePreparationRecordByUid with the appropriate status constants.
Experiment Record Lifecycle
Experiment records are defined in data/experiment.go and represent actual chaos experiments in execution. The ExperimentModel struct contains fields for Uid, Command, SubCommand, Flag, Status, and Error.
The status lifecycle for experiment records includes:
Created(initial state)Success(completed successfully)Error(execution failed)Destroyed(explicitly stopped or cleaned up)
The actionRunEFunc in cli/cmd/create.go handles these transitions, updating the record via UpdateExperimentModelByUid after execution completes. Additionally, the optional endpointCallBack function can POST experiment results to an external HTTP endpoint for integration with monitoring systems.
Command Implementation in Source Code
Examining the source code reveals the architectural patterns that distinguish these commands.
Prepare Command Implementation (cli/cmd/prepare.go)
The PrepareCommand struct implements the command interface in cli/cmd/prepare.go. The Init method registers the command with Cobra:
func (pc *PrepareCommand) Init() {
pc.command = &cobra.Command{
Use: "prepare",
Aliases: []string{"p"},
Short: "Prepare to experiment",
// ...
}
}
The insertPrepareRecord function (lines 62-84) generates a UID and persists the initial record:
func insertPrepareRecord(prepareType, processName, port, processId string) (*data.PreparationRecord, error) {
uid, err := util.GenerateUid()
// ...
record := &data.PreparationRecord{Uid: uid, ProgramType: prepareType, ...}
err = GetDS().InsertPreparationRecord(record)
}
The handlePrepareResponse function (lines 86-118) updates the record status based on execution results, transitioning to Running on success or Error on failure.
Create Command Implementation (cli/cmd/create.go)
The CreateCommand struct in cli/cmd/create.go handles experiment lifecycle management. The Init method registers the command:
func (cc *CreateCommand) Init() {
cc.command = &cobra.Command{
Use: "create",
Short: "Create a chaos engineering experiment",
// ...
}
}
The core execution logic resides in actionRunEFunc (lines 104-229), which:
- Builds the experiment model via
createExpModel - Inserts the record using
actionCommand.recordExpModel - Determines execution mode (sync vs async)
- Executes the appropriate executor
- Updates status and triggers optional endpoint callbacks
The endpointCallBack function (lines 32-49) provides optional HTTP reporting:
func endpointCallBack(ctx context.Context, endpoint, uid string, response *spec.Response) {
if endpoint != "" {
// POST result to external endpoint
}
}
Practical Usage Examples
Understanding the distinction becomes clearer through concrete examples.
Preparing a Java Environment
# Attach the chaosblade-jvm agent to a Tomcat process
blade prepare jvm --process tomcat
# Output: Returns a UID (e.g., 1234567890abcdef)
# Status transitions: Created → Running
This command modifies the target JVM by attaching the ChaosBlade agent, but does not inject any chaos. The returned UID can be used later to revoke the preparation via blade destroy <UID>.
Creating a Synchronous Experiment
# Immediately start a CPU load experiment
blade create cpu load --cpu-percent 60
# Output: Returns UID, blocks until completion or interruption
# Status transitions: Created → Success/Error
This command immediately begins consuming 60% of CPU resources and blocks the terminal until the experiment is stopped or encounters an error.
Creating an Asynchronous Experiment with Callback
# Launch network latency in background with webhook reporting
blade create network delay --interface eth0 --time 2000 \
--async --endpoint http://monitoring.example.com/chaos-callback
# Output: Immediately returns UID
# Background process runs nohup, later POSTs result to endpoint
This launches a 2000ms network delay experiment in the background, allowing the user to continue using the terminal. Upon completion, ChaosBlade POSTs the results to the specified endpoint.
Summary
-
Purpose distinction: The
preparecommand establishes runtime prerequisites (JVM agents, Kubernetes sidecars) without injecting chaos, whilecreatelaunches actual experiments (CPU, network, disk attacks) and manages their lifecycle. -
Data models:
preparepersistsPreparationRecordentries in the preparation table with statuses (Created,Running,Error,Revoked), whereascreatepersistsExperimentModelentries in the experiment table with statuses (Created,Success,Error,Destroyed). -
Execution modes:
preparealways runs synchronously to completion, whilecreatesupports both synchronous blocking execution and asynchronous background execution via the--asyncflag with optional webhook callbacks. -
Source locations: Implementation resides in
cli/cmd/prepare.go(prepare logic,insertPrepareRecord,handlePrepareResponse) andcli/cmd/create.go(experiment logic,actionRunEFunc,endpointCallBack).
Frequently Asked Questions
Can I run a chaos experiment without using prepare first?
Yes, for many experiment types such as CPU load or network delay, you can run blade create directly without any prior preparation. However, for Java-based chaos experiments (JVM attacks), you must first run blade prepare jvm to attach the ChaosBlade agent to the target process before creating any JVM-related experiments.
What happens to the preparation record after I destroy the experiment?
The preparation record remains in the database with its status updated to Revoked when you explicitly destroy it using blade destroy <UID>. Unlike experiment records that transition to Destroyed, preparation records track the lifecycle of the environment setup itself and maintain a distinct Revoked state to indicate the agent or sidecar has been removed.
How do I check the status of a prepare or create command?
You can check the status of both preparation and experiment records using the blade status command followed by the UID. For example, blade status 1234567890abcdef queries the database and returns the current state (e.g., Running, Success, Error) along with error details if the operation failed. This works for both preparation records created by prepare and experiment records created by create.
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 →