# Merobox
A powerful Python CLI tool for managing Calimero nodes in Docker containers and executing complex workflows with dynamic value capture and script execution capabilities.
## 🚀 Features
- **Node Management**: Start, stop, and manage Calimero nodes in Docker containers
- **Application Installation**: Install applications on Calimero nodes
- **Context Management**: Create and manage Calimero contexts
- **Identity Management**: Generate and manage identities for contexts
- **Workflow Execution**: Execute complex workflows defined in YAML files using the bootstrap command
- **Script Steps**: Execute custom scripts on Docker images or running nodes
- **Contract Execution**: Execute contract calls, view calls, and function calls
- **Health Monitoring**: Check the health status of running nodes
- **Context Joining**: Join contexts using invitations
- **Automated Workflows**: Complete automation of multi-step Calimero operations
- **Dynamic Value Capture**: Automatic capture and reuse of generated values
- **Repeat Steps**: Execute sets of operations multiple times with iteration variables
## 📦 Installation
### Option 1: Install from Source
```bash
# Clone the repository
git clone https://github.com/your-username/merobox.git
cd merobox
# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Install merobox in development mode
pip install -e .
```
### Option 2: Install from PyPI
```bash
pip install merobox
```
### Option 3: Install from Wheel
```bash
# Download the latest wheel from releases
pip install merobox-*.whl
```
### Prerequisites
- **Python 3.8+**
- **Docker** (running and accessible)
- **Docker Compose** (optional, for advanced setups)
## 🎯 Quick Start
### 1. Verify Installation
```bash
merobox --help
```
### 2. Start Your First Nodes
```bash
# Start 2 Calimero nodes
merobox run --count 2
# Check node status
merobox list
# Monitor node health
merobox health
```
### 3. Run a Sample Workflow
```bash
# Create a sample workflow
merobox bootstrap --create-sample
# Run the sample workflow
merobox bootstrap workflow-example.yml
```
## 📚 Usage
### Basic Commands
```bash
# List running nodes
merobox list
# Start nodes
merobox run --count 2
# Check node health
merobox health
# Stop nodes
merobox stop
# View node logs
merobox logs calimero-node-1
```
### Workflow Execution (Bootstrap)
Execute complex workflows defined in YAML files using the bootstrap command:
```bash
# Run a workflow
merobox bootstrap workflow-example.yml
# Create a sample workflow
merobox bootstrap --create-sample
# Run with verbose output
merobox bootstrap --verbose workflow-example.yml
```
### Application Management
```bash
# Install application on a node
merobox install --node calimero-node-1 --path ./app.wasm --dev
# Install from URL
merobox install --node calimero-node-1 --url https://example.com/app.wasm
```
### Context Management
```bash
# Create a context
merobox context create --node calimero-node-1 --application-id your-app-id
# List contexts
merobox context list --node calimero-node-1
# Get context details
merobox context get --node calimero-node-1 --context-id your-context-id
```
### Identity Management
```bash
# Generate identity
merobox identity generate --node calimero-node-1
# Invite identity to context
merobox identity invite \
--node calimero-node-1 \
--context-id your-context-id \
--granter-id granter-public-key \
--grantee-id grantee-public-key \
--capability member
```
### Context Joining
```bash
# Join a context using invitation
merobox join context \
--node calimero-node-2 \
--context-id your-context-id \
--invitee-id your-public-key \
--invitation invitation-data
```
### Contract Execution
Execute contract calls directly:
```bash
# Contract call
merobox call \
--node calimero-node-1 \
--context-id your-context-id \
--function set \
--args '{"key": "hello", "value": "world"}'
# View call (read-only)
merobox call \
--node calimero-node-1 \
--context-id your-context-id \
--function get \
--args '{"key": "hello"}'
```
## 🔧 Workflow Configuration
### Basic Workflow Structure
```yaml
name: "My Calimero Workflow"
description: "Description of what this workflow does"
nodes:
count: 2
prefix: "calimero-node"
image: "ghcr.io/calimero-network/merod:edge"
steps:
- name: "Install Application"
type: "install_application"
node: "calimero-node-1"
path: "./app.wasm"
dev: true
```
### Node Configuration Options
#### Simple Multiple Nodes
```yaml
nodes:
count: 2
prefix: "calimero-node"
chain_id: "testnet-1"
image: "ghcr.io/calimero-network/merod:edge"
```
#### Individual Node Configuration
```yaml
nodes:
node1:
port: 2428
rpc_port: 2528
chain_id: "testnet-1"
data_dir: "./data/custom-node1"
node2:
port: 2429
rpc_port: 2529
chain_id: "testnet-1"
```
### Node Management Flags
Control node behavior with two key flags:
```yaml
# Control node restart at beginning
restart: false
# Control node stopping at end
stop_all_nodes: false
```
#### Flag Combinations
| restart | stop_all_nodes | Behavior |
|---------|----------------|----------|
| `true` | `true` | Fresh start, complete cleanup |
| `false` | `false` | Reuse existing, leave running |
| `true` | `false` | Fresh start, leave running |
| `false` | `true` | Reuse existing, complete cleanup |
## 📝 Step Types
### Core Steps
#### `install_application`
Installs an application on a specified node.
```yaml
- name: "Install App"
type: "install_application"
node: "calimero-node-1"
path: "./app.wasm"
dev: true
```
**Dynamic Values Captured:**
- Application ID (stored as `{{install.node_name}}`)
#### `create_context`
Creates a context for an application.
```yaml
- name: "Create Context"
type: "create_context"
node: "calimero-node-1"
application_id: "{{install.calimero-node-1}}"
```
**Dynamic Values Captured:**
- Context ID (stored as `{{context.node_name}}`)
- Member Public Key (accessible as `{{context.node_name.memberPublicKey}}`)
#### `create_identity`
Generates a new identity on a node.
```yaml
- name: "Generate Identity"
type: "create_identity"
node: "calimero-node-2"
```
**Dynamic Values Captured:**
- Public key (stored as `{{identity.node_name}}`)
#### `invite_identity`
Invites an identity to a context.
```yaml
- name: "Invite Identity"
type: "invite_identity"
node: "calimero-node-1"
context_id: "{{context.calimero-node-1}}"
granter_id: "{{context.calimero-node-1.memberPublicKey}}"
grantee_id: "{{identity.calimero-node-2}}"
capability: "member"
```
**Dynamic Values Captured:**
- Invitation data (stored as `{{invite.node_name_identity.node_name}}`)
#### `join_context`
Joins a context using an invitation.
```yaml
- name: "Join Context"
type: "join_context"
node: "calimero-node-2"
context_id: "{{context.calimero-node-1}}"
invitee_id: "{{identity.calimero-node-2}}"
invitation: "{{invite.calimero-node-1_identity.calimero-node-2}}"
```
#### `call`
Executes contract calls, view calls, or function calls.
```yaml
- name: "Set Key-Value"
type: "call"
node: "calimero-node-1"
context_id: "{{context.calimero-node-1}}"
method: "set"
args:
key: "hello"
value: "world"
```
**Features:**
- Automatically detects and uses the correct executor public key from the context
- Supports complex argument structures
- Comprehensive error reporting
#### `wait`
Pauses execution for a specified duration.
```yaml
- name: "Wait for Propagation"
type: "wait"
seconds: 5
```
### Advanced Steps
#### `script`
Execute custom scripts on Docker images or running nodes.
```yaml
- name: "Install Tools"
type: "script"
description: "Install curl and perf tools"
script: "./workflow-examples/scripts/install-tools.sh"
target: "image" # Execute on Docker image before nodes start
- name: "Health Check"
type: "script"
description: "Verify node health"
script: "./workflow-examples/scripts/health-check.sh"
target: "nodes" # Execute on all running nodes
```
**Target Types:**
- `"image"`: Execute on Docker image before nodes start
- `"nodes"`: Execute on all running Calimero nodes
#### `repeat`
Execute a set of nested steps multiple times.
```yaml
- name: "Repeat Operations"
type: "repeat"
count: 3
steps:
- name: "Set Key-Value"
type: "call"
node: "calimero-node-1"
context_id: "{{context.calimero-node-1}}"
method: "set"
args:
key: "key_{{iteration}}"
value: "value_{{iteration}}"
- name: "Wait for Propagation"
type: "wait"
seconds: 2
```
**Iteration Variables:**
- `{{iteration}}` - Current iteration number (1-based)
- `{{iteration_index}}` - Current iteration index (0-based)
## 🔄 Dynamic Values and Placeholders
The bootstrap command automatically captures dynamic values from each step and makes them available to subsequent steps using placeholders.
### Placeholder Format
```
{{type.node_name}}
{{type.node_name.field_name}}
```
### Available Placeholders
- `{{install.node_name}}` - Application ID from installation
- `{{context.node_name}}` - Context ID from context creation
- `{{context.node_name.memberPublicKey}}` - Member public key from context
- `{{identity.node_name}}` - Public key from identity generation
- `{{invite.node_name_identity.node_name}}` - Invitation data from invitation
- `{{iteration}}` - Current iteration number in repeat steps
### Example Workflow with Dynamic Values
```yaml
steps:
# Install application
- name: "Install App"
type: "install_application"
node: "calimero-node-1"
path: "./app.wasm"
dev: true
# Create context using captured app ID
- name: "Create Context"
type: "create_context"
node: "calimero-node-1"
application_id: "{{install.calimero-node-1}}"
# Generate identity
- name: "Generate Identity"
type: "create_identity"
node: "calimero-node-2"
# Invite using captured values
- name: "Invite Identity"
type: "invite_identity"
node: "calimero-node-1"
context_id: "{{context.calimero-node-1}}"
granter_id: "{{context.calimero-node-1.memberPublicKey}}"
grantee_id: "{{identity.calimero-node-2}}"
capability: "member"
# Join using invitation
- name: "Join Context"
type: "join_context"
node: "calimero-node-2"
context_id: "{{context.calimero-node-1}}"
invitee_id: "{{identity.calimero-node-2}}"
invitation: "{{invite.calimero-node-1_identity.calimero-node-2}}"
# Execute contract calls
- name: "Set Key-Value"
type: "call"
node: "calimero-node-1"
context_id: "{{context.calimero-node-1}}"
method: "set"
args:
key: "hello"
value: "world"
```
## 📁 Workflow Examples
### Basic Workflow
See `workflow-examples/workflow-example.yml` for a complete workflow example.
### Script Steps Workflow
See `workflow-examples/workflow-script-test.yml` for script step examples.
### Repeat Steps Workflow
See `workflow-examples/workflow-repeat-example.yml` for repeat step examples.
### Node Management Workflow
See `workflow-examples/workflow-restart-example.yml` for node management examples.
## 🛠️ Script Steps
### Creating Scripts
Scripts can be written in any language supported by the container (typically bash):
```bash
#!/bin/bash
echo "🚀 Script execution started on $(hostname)"
# Check merod process
if pgrep -f merod > /dev/null; then
echo "✅ merod process running"
else
echo "❌ merod process not found"
exit 1
fi
echo "✅ Script completed successfully"
```
### Script Requirements
#### Image Target Scripts
- **Permissions**: Scripts are mounted read-only
- **User**: Runs as default user (often non-root)
- **Package Installation**: May require root privileges
- **Cleanup**: Temporary containers are automatically cleaned up
#### Nodes Target Scripts
- **Permissions**: Scripts are copied with executable permissions (0o755)
- **User**: Runs as root in Calimero node containers
- **Access**: Full access to node data directories and processes
- **Cleanup**: Scripts are automatically removed after execution
### Install Tools Script (`workflow-examples/scripts/install-tools.sh`)
```bash
#!/bin/bash
echo "🚀 Installing tools on Docker image..."
# Detect package manager
if command -v apt-get &> /dev/null; then
echo "📦 Using apt-get"
apt-get update
apt-get install -y curl perf
elif command -v yum &> /dev/null; then
echo "📦 Using yum"
yum install -y curl perf
else
echo "⚠️ No supported package manager found"
exit 1
fi
echo "✅ Tools installed successfully"
```
### Health Check Script (`workflow-examples/scripts/health-check.sh`)
```bash
#!/bin/bash
echo "🔍 Health check on $(hostname)"
# Check merod process
if pgrep -f merod > /dev/null; then
echo "✅ merod process running"
else
echo "❌ merod process not found"
exit 1
fi
# Check data directory
if [ -d "/app/data" ]; then
echo "✅ Data directory exists"
else
echo "❌ Data directory missing"
exit 1
fi
echo "✅ Health check passed"
```
## 🔍 Troubleshooting
### Common Issues
1. **Script Not Found**
- Ensure script path is correct relative to workflow file
- Use absolute paths if needed
- Check file permissions
2. **Permission Denied**
- Image target scripts may run as non-root user
- Use `sudo` or run as root in container
- Check file permissions and ownership
3. **Workflow Stops Unexpectedly**
- Script failures stop the entire workflow
- Check script exit codes
- Review error messages in output
4. **Dynamic Values Not Working**
- Verify step names match placeholder references
- Check that previous steps completed successfully
- Use `--verbose` flag for detailed output
### Debugging Tips
- Use `--verbose` flag for detailed execution information
- Check script output in workflow logs
- Test scripts independently in containers
- Verify script permissions and dependencies
- Use `merobox bootstrap validate <file>` to check configuration
## 🏗️ Architecture
The tool is built with a modular architecture:
- **Commands**: Individual CLI commands for different operations
- **Manager**: Docker container management
- **WorkflowExecutor**: Workflow orchestration and execution with dynamic value capture
- **Steps**: Modular step executors for different operation types
- **AdminClient**: Admin API operations (no authentication required)
- **JsonRpcClient**: JSON-RPC operations (requires authentication)
## 🎯 Key Features
### Bootstrap Command
- **Automated Workflows**: Execute multi-step operations with a single command
- **Dynamic Value Capture**: Automatic capture and reuse of generated values
- **Error Handling**: Comprehensive error handling and validation
- **Node Management**: Automatic node startup and readiness checking
- **Flexible Configuration**: Support for both simple and complex node configurations
### Script Steps
- **Flexibility**: Position scripts anywhere in workflow
- **Reusability**: Use same scripts in multiple workflows
- **Maintainability**: Centralized script management
- **Debugging**: Better error handling and logging
- **Integration**: Seamless workflow integration
### Repeat Steps
- **Iteration Support**: Execute operations multiple times
- **Dynamic Variables**: Use iteration variables in nested steps
- **Nested Steps**: Support for all step types as nested steps
- **Error Handling**: Comprehensive error handling across iterations
## 🤝 Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request
## 📄 License
[Add your license here]
## 📚 Additional Resources
- **Changelog**: See `CHANGELOG.md` for version history
- **Publishing**: See `PUBLISHING.md` for release information
- **Workflow Examples**: See `workflow-examples/` directory for complete examples
- **Issues**: Report bugs and request features on GitHub
Raw data
{
"_id": null,
"home_page": "https://github.com/merobox/merobox",
"name": "merobox",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Merobox Team <team@merobox.com>",
"keywords": "calimero, blockchain, docker, cli, workflow",
"author": "Merobox Team",
"author_email": "Merobox Team <team@merobox.com>",
"download_url": "https://files.pythonhosted.org/packages/5f/b6/ccec44531516d80aaec7225a063d4461e6f0f23ed7ff4289e55f5f0a2e84/merobox-0.1.7.tar.gz",
"platform": null,
"description": "# Merobox\n\nA powerful Python CLI tool for managing Calimero nodes in Docker containers and executing complex workflows with dynamic value capture and script execution capabilities.\n\n## \ud83d\ude80 Features\n\n- **Node Management**: Start, stop, and manage Calimero nodes in Docker containers\n- **Application Installation**: Install applications on Calimero nodes\n- **Context Management**: Create and manage Calimero contexts\n- **Identity Management**: Generate and manage identities for contexts\n- **Workflow Execution**: Execute complex workflows defined in YAML files using the bootstrap command\n- **Script Steps**: Execute custom scripts on Docker images or running nodes\n- **Contract Execution**: Execute contract calls, view calls, and function calls\n- **Health Monitoring**: Check the health status of running nodes\n- **Context Joining**: Join contexts using invitations\n- **Automated Workflows**: Complete automation of multi-step Calimero operations\n- **Dynamic Value Capture**: Automatic capture and reuse of generated values\n- **Repeat Steps**: Execute sets of operations multiple times with iteration variables\n\n## \ud83d\udce6 Installation\n\n### Option 1: Install from Source\n\n```bash\n# Clone the repository\ngit clone https://github.com/your-username/merobox.git\ncd merobox\n\n# Create and activate virtual environment\npython3 -m venv venv\nsource venv/bin/activate # On Windows: venv\\Scripts\\activate\n\n# Install dependencies\npip install -r requirements.txt\n\n# Install merobox in development mode\npip install -e .\n```\n\n### Option 2: Install from PyPI\n\n```bash\npip install merobox\n```\n\n### Option 3: Install from Wheel\n\n```bash\n# Download the latest wheel from releases\npip install merobox-*.whl\n```\n\n### Prerequisites\n\n- **Python 3.8+**\n- **Docker** (running and accessible)\n- **Docker Compose** (optional, for advanced setups)\n\n## \ud83c\udfaf Quick Start\n\n### 1. Verify Installation\n\n```bash\nmerobox --help\n```\n\n### 2. Start Your First Nodes\n\n```bash\n# Start 2 Calimero nodes\nmerobox run --count 2\n\n# Check node status\nmerobox list\n\n# Monitor node health\nmerobox health\n```\n\n### 3. Run a Sample Workflow\n\n```bash\n# Create a sample workflow\nmerobox bootstrap --create-sample\n\n# Run the sample workflow\nmerobox bootstrap workflow-example.yml\n```\n\n## \ud83d\udcda Usage\n\n### Basic Commands\n\n```bash\n# List running nodes\nmerobox list\n\n# Start nodes\nmerobox run --count 2\n\n# Check node health\nmerobox health\n\n# Stop nodes\nmerobox stop\n\n# View node logs\nmerobox logs calimero-node-1\n```\n\n### Workflow Execution (Bootstrap)\n\nExecute complex workflows defined in YAML files using the bootstrap command:\n\n```bash\n# Run a workflow\nmerobox bootstrap workflow-example.yml\n\n# Create a sample workflow\nmerobox bootstrap --create-sample\n\n# Run with verbose output\nmerobox bootstrap --verbose workflow-example.yml\n```\n\n### Application Management\n\n```bash\n# Install application on a node\nmerobox install --node calimero-node-1 --path ./app.wasm --dev\n\n# Install from URL\nmerobox install --node calimero-node-1 --url https://example.com/app.wasm\n```\n\n### Context Management\n\n```bash\n# Create a context\nmerobox context create --node calimero-node-1 --application-id your-app-id\n\n# List contexts\nmerobox context list --node calimero-node-1\n\n# Get context details\nmerobox context get --node calimero-node-1 --context-id your-context-id\n```\n\n### Identity Management\n\n```bash\n# Generate identity\nmerobox identity generate --node calimero-node-1\n\n# Invite identity to context\nmerobox identity invite \\\n --node calimero-node-1 \\\n --context-id your-context-id \\\n --granter-id granter-public-key \\\n --grantee-id grantee-public-key \\\n --capability member\n```\n\n### Context Joining\n\n```bash\n# Join a context using invitation\nmerobox join context \\\n --node calimero-node-2 \\\n --context-id your-context-id \\\n --invitee-id your-public-key \\\n --invitation invitation-data\n```\n\n### Contract Execution\n\nExecute contract calls directly:\n\n```bash\n# Contract call\nmerobox call \\\n --node calimero-node-1 \\\n --context-id your-context-id \\\n --function set \\\n --args '{\"key\": \"hello\", \"value\": \"world\"}'\n\n# View call (read-only)\nmerobox call \\\n --node calimero-node-1 \\\n --context-id your-context-id \\\n --function get \\\n --args '{\"key\": \"hello\"}'\n```\n\n## \ud83d\udd27 Workflow Configuration\n\n### Basic Workflow Structure\n\n```yaml\nname: \"My Calimero Workflow\"\ndescription: \"Description of what this workflow does\"\n\nnodes:\n count: 2\n prefix: \"calimero-node\"\n image: \"ghcr.io/calimero-network/merod:edge\"\n\nsteps:\n - name: \"Install Application\"\n type: \"install_application\"\n node: \"calimero-node-1\"\n path: \"./app.wasm\"\n dev: true\n```\n\n### Node Configuration Options\n\n#### Simple Multiple Nodes\n```yaml\nnodes:\n count: 2\n prefix: \"calimero-node\"\n chain_id: \"testnet-1\"\n image: \"ghcr.io/calimero-network/merod:edge\"\n```\n\n#### Individual Node Configuration\n```yaml\nnodes:\n node1:\n port: 2428\n rpc_port: 2528\n chain_id: \"testnet-1\"\n data_dir: \"./data/custom-node1\"\n node2:\n port: 2429\n rpc_port: 2529\n chain_id: \"testnet-1\"\n```\n\n### Node Management Flags\n\nControl node behavior with two key flags:\n\n```yaml\n# Control node restart at beginning\nrestart: false\n\n# Control node stopping at end\nstop_all_nodes: false\n```\n\n#### Flag Combinations\n\n| restart | stop_all_nodes | Behavior |\n|---------|----------------|----------|\n| `true` | `true` | Fresh start, complete cleanup |\n| `false` | `false` | Reuse existing, leave running |\n| `true` | `false` | Fresh start, leave running |\n| `false` | `true` | Reuse existing, complete cleanup |\n\n## \ud83d\udcdd Step Types\n\n### Core Steps\n\n#### `install_application`\nInstalls an application on a specified node.\n\n```yaml\n- name: \"Install App\"\n type: \"install_application\"\n node: \"calimero-node-1\"\n path: \"./app.wasm\"\n dev: true\n```\n\n**Dynamic Values Captured:**\n- Application ID (stored as `{{install.node_name}}`)\n\n#### `create_context`\nCreates a context for an application.\n\n```yaml\n- name: \"Create Context\"\n type: \"create_context\"\n node: \"calimero-node-1\"\n application_id: \"{{install.calimero-node-1}}\"\n```\n\n**Dynamic Values Captured:**\n- Context ID (stored as `{{context.node_name}}`)\n- Member Public Key (accessible as `{{context.node_name.memberPublicKey}}`)\n\n#### `create_identity`\nGenerates a new identity on a node.\n\n```yaml\n- name: \"Generate Identity\"\n type: \"create_identity\"\n node: \"calimero-node-2\"\n```\n\n**Dynamic Values Captured:**\n- Public key (stored as `{{identity.node_name}}`)\n\n#### `invite_identity`\nInvites an identity to a context.\n\n```yaml\n- name: \"Invite Identity\"\n type: \"invite_identity\"\n node: \"calimero-node-1\"\n context_id: \"{{context.calimero-node-1}}\"\n granter_id: \"{{context.calimero-node-1.memberPublicKey}}\"\n grantee_id: \"{{identity.calimero-node-2}}\"\n capability: \"member\"\n```\n\n**Dynamic Values Captured:**\n- Invitation data (stored as `{{invite.node_name_identity.node_name}}`)\n\n#### `join_context`\nJoins a context using an invitation.\n\n```yaml\n- name: \"Join Context\"\n type: \"join_context\"\n node: \"calimero-node-2\"\n context_id: \"{{context.calimero-node-1}}\"\n invitee_id: \"{{identity.calimero-node-2}}\"\n invitation: \"{{invite.calimero-node-1_identity.calimero-node-2}}\"\n```\n\n#### `call`\nExecutes contract calls, view calls, or function calls.\n\n```yaml\n- name: \"Set Key-Value\"\n type: \"call\"\n node: \"calimero-node-1\"\n context_id: \"{{context.calimero-node-1}}\"\n method: \"set\"\n args:\n key: \"hello\"\n value: \"world\"\n```\n\n**Features:**\n- Automatically detects and uses the correct executor public key from the context\n- Supports complex argument structures\n- Comprehensive error reporting\n\n#### `wait`\nPauses execution for a specified duration.\n\n```yaml\n- name: \"Wait for Propagation\"\n type: \"wait\"\n seconds: 5\n```\n\n### Advanced Steps\n\n#### `script`\nExecute custom scripts on Docker images or running nodes.\n\n```yaml\n- name: \"Install Tools\"\n type: \"script\"\n description: \"Install curl and perf tools\"\n script: \"./workflow-examples/scripts/install-tools.sh\"\n target: \"image\" # Execute on Docker image before nodes start\n\n- name: \"Health Check\"\n type: \"script\"\n description: \"Verify node health\"\n script: \"./workflow-examples/scripts/health-check.sh\"\n target: \"nodes\" # Execute on all running nodes\n```\n\n**Target Types:**\n- `\"image\"`: Execute on Docker image before nodes start\n- `\"nodes\"`: Execute on all running Calimero nodes\n\n#### `repeat`\nExecute a set of nested steps multiple times.\n\n```yaml\n- name: \"Repeat Operations\"\n type: \"repeat\"\n count: 3\n steps:\n - name: \"Set Key-Value\"\n type: \"call\"\n node: \"calimero-node-1\"\n context_id: \"{{context.calimero-node-1}}\"\n method: \"set\"\n args:\n key: \"key_{{iteration}}\"\n value: \"value_{{iteration}}\"\n \n - name: \"Wait for Propagation\"\n type: \"wait\"\n seconds: 2\n```\n\n**Iteration Variables:**\n- `{{iteration}}` - Current iteration number (1-based)\n- `{{iteration_index}}` - Current iteration index (0-based)\n\n## \ud83d\udd04 Dynamic Values and Placeholders\n\nThe bootstrap command automatically captures dynamic values from each step and makes them available to subsequent steps using placeholders.\n\n### Placeholder Format\n\n```\n{{type.node_name}}\n{{type.node_name.field_name}}\n```\n\n### Available Placeholders\n\n- `{{install.node_name}}` - Application ID from installation\n- `{{context.node_name}}` - Context ID from context creation\n- `{{context.node_name.memberPublicKey}}` - Member public key from context\n- `{{identity.node_name}}` - Public key from identity generation\n- `{{invite.node_name_identity.node_name}}` - Invitation data from invitation\n- `{{iteration}}` - Current iteration number in repeat steps\n\n### Example Workflow with Dynamic Values\n\n```yaml\nsteps:\n # Install application\n - name: \"Install App\"\n type: \"install_application\"\n node: \"calimero-node-1\"\n path: \"./app.wasm\"\n dev: true\n\n # Create context using captured app ID\n - name: \"Create Context\"\n type: \"create_context\"\n node: \"calimero-node-1\"\n application_id: \"{{install.calimero-node-1}}\"\n\n # Generate identity\n - name: \"Generate Identity\"\n type: \"create_identity\"\n node: \"calimero-node-2\"\n\n # Invite using captured values\n - name: \"Invite Identity\"\n type: \"invite_identity\"\n node: \"calimero-node-1\"\n context_id: \"{{context.calimero-node-1}}\"\n granter_id: \"{{context.calimero-node-1.memberPublicKey}}\"\n grantee_id: \"{{identity.calimero-node-2}}\"\n capability: \"member\"\n\n # Join using invitation\n - name: \"Join Context\"\n type: \"join_context\"\n node: \"calimero-node-2\"\n context_id: \"{{context.calimero-node-1}}\"\n invitee_id: \"{{identity.calimero-node-2}}\"\n invitation: \"{{invite.calimero-node-1_identity.calimero-node-2}}\"\n\n # Execute contract calls\n - name: \"Set Key-Value\"\n type: \"call\"\n node: \"calimero-node-1\"\n context_id: \"{{context.calimero-node-1}}\"\n method: \"set\"\n args:\n key: \"hello\"\n value: \"world\"\n```\n\n## \ud83d\udcc1 Workflow Examples\n\n### Basic Workflow\nSee `workflow-examples/workflow-example.yml` for a complete workflow example.\n\n### Script Steps Workflow\nSee `workflow-examples/workflow-script-test.yml` for script step examples.\n\n### Repeat Steps Workflow\nSee `workflow-examples/workflow-repeat-example.yml` for repeat step examples.\n\n### Node Management Workflow\nSee `workflow-examples/workflow-restart-example.yml` for node management examples.\n\n## \ud83d\udee0\ufe0f Script Steps\n\n### Creating Scripts\n\nScripts can be written in any language supported by the container (typically bash):\n\n```bash\n#!/bin/bash\necho \"\ud83d\ude80 Script execution started on $(hostname)\"\n\n# Check merod process\nif pgrep -f merod > /dev/null; then\n echo \"\u2705 merod process running\"\nelse\n echo \"\u274c merod process not found\"\n exit 1\nfi\n\necho \"\u2705 Script completed successfully\"\n```\n\n### Script Requirements\n\n#### Image Target Scripts\n- **Permissions**: Scripts are mounted read-only\n- **User**: Runs as default user (often non-root)\n- **Package Installation**: May require root privileges\n- **Cleanup**: Temporary containers are automatically cleaned up\n\n#### Nodes Target Scripts\n- **Permissions**: Scripts are copied with executable permissions (0o755)\n- **User**: Runs as root in Calimero node containers\n- **Access**: Full access to node data directories and processes\n- **Cleanup**: Scripts are automatically removed after execution\n\n### Install Tools Script (`workflow-examples/scripts/install-tools.sh`)\n\n```bash\n#!/bin/bash\necho \"\ud83d\ude80 Installing tools on Docker image...\"\n\n# Detect package manager\nif command -v apt-get &> /dev/null; then\n echo \"\ud83d\udce6 Using apt-get\"\n apt-get update\n apt-get install -y curl perf\nelif command -v yum &> /dev/null; then\n echo \"\ud83d\udce6 Using yum\"\n yum install -y curl perf\nelse\n echo \"\u26a0\ufe0f No supported package manager found\"\n exit 1\nfi\n\necho \"\u2705 Tools installed successfully\"\n```\n\n### Health Check Script (`workflow-examples/scripts/health-check.sh`)\n\n```bash\n#!/bin/bash\necho \"\ud83d\udd0d Health check on $(hostname)\"\n\n# Check merod process\nif pgrep -f merod > /dev/null; then\n echo \"\u2705 merod process running\"\nelse\n echo \"\u274c merod process not found\"\n exit 1\nfi\n\n# Check data directory\nif [ -d \"/app/data\" ]; then\n echo \"\u2705 Data directory exists\"\nelse\n echo \"\u274c Data directory missing\"\n exit 1\nfi\n\necho \"\u2705 Health check passed\"\n```\n\n## \ud83d\udd0d Troubleshooting\n\n### Common Issues\n\n1. **Script Not Found**\n - Ensure script path is correct relative to workflow file\n - Use absolute paths if needed\n - Check file permissions\n\n2. **Permission Denied**\n - Image target scripts may run as non-root user\n - Use `sudo` or run as root in container\n - Check file permissions and ownership\n\n3. **Workflow Stops Unexpectedly**\n - Script failures stop the entire workflow\n - Check script exit codes\n - Review error messages in output\n\n4. **Dynamic Values Not Working**\n - Verify step names match placeholder references\n - Check that previous steps completed successfully\n - Use `--verbose` flag for detailed output\n\n### Debugging Tips\n\n- Use `--verbose` flag for detailed execution information\n- Check script output in workflow logs\n- Test scripts independently in containers\n- Verify script permissions and dependencies\n- Use `merobox bootstrap validate <file>` to check configuration\n\n## \ud83c\udfd7\ufe0f Architecture\n\nThe tool is built with a modular architecture:\n\n- **Commands**: Individual CLI commands for different operations\n- **Manager**: Docker container management\n- **WorkflowExecutor**: Workflow orchestration and execution with dynamic value capture\n- **Steps**: Modular step executors for different operation types\n- **AdminClient**: Admin API operations (no authentication required)\n- **JsonRpcClient**: JSON-RPC operations (requires authentication)\n\n## \ud83c\udfaf Key Features\n\n### Bootstrap Command\n- **Automated Workflows**: Execute multi-step operations with a single command\n- **Dynamic Value Capture**: Automatic capture and reuse of generated values\n- **Error Handling**: Comprehensive error handling and validation\n- **Node Management**: Automatic node startup and readiness checking\n- **Flexible Configuration**: Support for both simple and complex node configurations\n\n### Script Steps\n- **Flexibility**: Position scripts anywhere in workflow\n- **Reusability**: Use same scripts in multiple workflows\n- **Maintainability**: Centralized script management\n- **Debugging**: Better error handling and logging\n- **Integration**: Seamless workflow integration\n\n### Repeat Steps\n- **Iteration Support**: Execute operations multiple times\n- **Dynamic Variables**: Use iteration variables in nested steps\n- **Nested Steps**: Support for all step types as nested steps\n- **Error Handling**: Comprehensive error handling across iterations\n\n## \ud83e\udd1d Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests if applicable\n5. Submit a pull request\n\n## \ud83d\udcc4 License\n\n[Add your license here]\n\n## \ud83d\udcda Additional Resources\n\n- **Changelog**: See `CHANGELOG.md` for version history\n- **Publishing**: See `PUBLISHING.md` for release information\n- **Workflow Examples**: See `workflow-examples/` directory for complete examples\n- **Issues**: Report bugs and request features on GitHub\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Python CLI tool for managing Calimero nodes in Docker containers",
"version": "0.1.7",
"project_urls": {
"Changelog": "https://github.com/merobox/merobox/blob/main/CHANGELOG.md",
"Documentation": "https://github.com/merobox/merobox#readme",
"Homepage": "https://github.com/merobox/merobox",
"Issues": "https://github.com/merobox/merobox/issues",
"Repository": "https://github.com/merobox/merobox"
},
"split_keywords": [
"calimero",
" blockchain",
" docker",
" cli",
" workflow"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "4b5dede45119b6039c8b109672c5d96c704b2645a29c4cfdc923b91310434709",
"md5": "7be5c8b79dc18c5b0311d6172248f18c",
"sha256": "b23462a0124231072de1c495cbcda80b25528fa1553fa98fb5e4b216079d4657"
},
"downloads": -1,
"filename": "merobox-0.1.7-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7be5c8b79dc18c5b0311d6172248f18c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 50001,
"upload_time": "2025-08-18T16:42:23",
"upload_time_iso_8601": "2025-08-18T16:42:23.908809Z",
"url": "https://files.pythonhosted.org/packages/4b/5d/ede45119b6039c8b109672c5d96c704b2645a29c4cfdc923b91310434709/merobox-0.1.7-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "5fb6ccec44531516d80aaec7225a063d4461e6f0f23ed7ff4289e55f5f0a2e84",
"md5": "715ace7e690843be7e94ac2019bd0aaf",
"sha256": "4e148e62cb30fa85696090b4f0b8d82f72d6a9546c0dfa014f774cf6a5ea90b3"
},
"downloads": -1,
"filename": "merobox-0.1.7.tar.gz",
"has_sig": false,
"md5_digest": "715ace7e690843be7e94ac2019bd0aaf",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 41573,
"upload_time": "2025-08-18T16:42:25",
"upload_time_iso_8601": "2025-08-18T16:42:25.442605Z",
"url": "https://files.pythonhosted.org/packages/5f/b6/ccec44531516d80aaec7225a063d4461e6f0f23ed7ff4289e55f5f0a2e84/merobox-0.1.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-18 16:42:25",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "merobox",
"github_project": "merobox",
"github_not_found": true,
"lcname": "merobox"
}