CLI Workflows
This page contains practical examples of common CLI workflows for managing Teenode resources. These examples can be adapted and combined for your specific needs.
Basic Setup Workflow
Complete setup from authentication to first deployment:
#!/bin/bash
# setup-new-account.sh
# 1. Authenticate
echo "Logging in..."
teenode auth login
# 2. Create team
read -p "Team name: " TEAM_NAME
teenode team create --name "$TEAM_NAME"
# 3. Create SSH key
KEY_NAME="$(whoami)-$(hostname)"
echo "Creating SSH key: $KEY_NAME"
ssh-keygen -t ed25519 -f ~/.ssh/$KEY_NAME -N ""
teenode ssh-key add --name "$KEY_NAME" --key-file ~/.ssh/$KEY_NAME.pub
# 4. Create first VM
read -p "VM name: " VM_NAME
teenode vm create \
--name "$VM_NAME" \
--region us-east \
--cpu 2 \
--memory 4096 \
--ssh-key "$KEY_NAME"
# 5. Get VM IP
sleep 10
VM_IP=$(teenode vm describe "$VM_NAME" | grep "IP Address" | awk '{print $NF}')
echo "VM ready at: $VM_IP"
# 6. Connect and verify
echo "Verifying connection..."
ssh -i ~/.ssh/$KEY_NAME root@$VM_IP "uname -a"
echo "✓ Setup complete!"Batch VM Creation
Create multiple VMs for a cluster:
#!/bin/bash
# create-cluster.sh
CLUSTER_NAME="web-cluster"
NODE_COUNT=3
REGION="us-east"
CPU=4
MEMORY=8192
echo "Creating $CLUSTER_NAME with $NODE_COUNT nodes..."
for i in $(seq 1 $NODE_COUNT); do
VM_NAME="$CLUSTER_NAME-node-$i"
echo "Creating $VM_NAME..."
teenode vm create \
--name "$VM_NAME" \
--region "$REGION" \
--cpu "$CPU" \
--memory "$MEMORY" \
--tags "cluster=$CLUSTER_NAME,role=worker" \
--wait
# Mark creation time
echo "✓ $VM_NAME created"
done
echo "✓ Cluster $CLUSTER_NAME created with $NODE_COUNT nodes"
# List all cluster VMs
echo "Cluster VMs:"
teenode vm list --tags "cluster=$CLUSTER_NAME"Multi-Project Monitoring
Monitor status across multiple projects:
#!/bin/bash
# monitor-all-projects.sh
echo "Project Status Report - $(date)"
echo "================================"
# Get all projects
PROJECTS=$(teenode project list -o json | jq -r '.[].name')
for project in $PROJECTS; do
echo ""
echo "Project: $project"
# Get project status
teenode project info "$project" -o json | jq '{
status: .status,
deployments: .deployment_count,
created: .created_at,
updated: .updated_at
}'
# Get latest deployment
LATEST=$(teenode deployment list "$project" --limit 1 -o json | jq -r '.[0]')
if [ "$LATEST" != "null" ]; then
echo " Latest deployment:"
echo "$LATEST" | jq '{
id: .id,
status: .status,
created: .created_at
}' | sed 's/^/ /'
fi
done
echo ""
echo "✓ Report complete"Automated Backup Workflow
Regular snapshots with automatic cleanup:
#!/bin/bash
# backup-vm.sh - Run with cron for automation
VM_NAME="$1"
RETENTION_DAYS=7
if [ -z "$VM_NAME" ]; then
echo "Usage: $0 <vm-name>"
exit 1
fi
SNAPSHOT_NAME="$VM_NAME-backup-$(date +%Y%m%d-%H%M%S)"
echo "Creating snapshot: \$SNAPSHOT_NAME"
teenode vm snapshot create "$VM_NAME" --name "\$SNAPSHOT_NAME"
if [ $? -ne 0 ]; then
echo "✗ Snapshot creation failed"
exit 1
fi
echo "✓ Snapshot created"
# Clean up old snapshots (older than RETENTION_DAYS)
echo "Cleaning up old snapshots..."
CUTOFF_DATE=$(date -d "$RETENTION_DAYS days ago" +%s)
teenode vm snapshot list "$VM_NAME" -o json | \
jq -r ".[] | select(.created_at < $CUTOFF_DATE) | .name" | \
while read -r old_snapshot; do
echo " Deleting $old_snapshot"
teenode vm snapshot delete "$VM_NAME" "$old_snapshot"
done
echo "✓ Backup workflow complete"
# Add to crontab:
# 0 2 * * * /usr/local/bin/backup-vm.sh my-vm 2>&1 | loggerEnvironment Synchronization
Keep environment variables in sync across environments:
#!/bin/bash
# sync-env.sh
SOURCE_PROJECT="$1"
TARGET_PROJECTS="${@:2}"
if [ -z "$SOURCE_PROJECT" ] || [ -z "$TARGET_PROJECTS" ]; then
echo "Usage: $0 <source-project> <target-project> [target-project...]"
exit 1
fi
echo "Syncing environment from $SOURCE_PROJECT to $TARGET_PROJECTS"
# Get environment from source
SOURCE_ENV=$(teenode env list "$SOURCE_PROJECT" -o json)
echo "$SOURCE_ENV" | jq -r 'to_entries[] | "(.key)=(.value)"' | \
while read -r var; do
KEY=$(echo "$var" | cut -d= -f1)
VALUE=$(echo "$var" | cut -d= -f2-)
for project in $TARGET_PROJECTS; do
echo "Setting $KEY in $project"
teenode env set "$project" "$KEY=$VALUE"
done
done
echo "✓ Environment synchronized"
# Verify
echo ""
echo "Verification:"
for project in $SOURCE_PROJECT $TARGET_PROJECTS; do
echo "$project:"
teenode env list "$project" | head -5
doneDeployment Automation
Auto-deploy with health checks:
#!/bin/bash
# auto-deploy.sh
PROJECT_NAME="$1"
BRANCH="${2:-main}"
HEALTH_CHECK_URL="${3:-http://localhost/health}"
if [ -z "$PROJECT_NAME" ]; then
echo "Usage: $0 <project-name> [branch] [health-check-url]"
exit 1
fi
echo "Deploying $PROJECT_NAME from $BRANCH..."
# Trigger deployment
DEPLOYMENT=$(teenode deployment create "$PROJECT_NAME" --branch "$BRANCH" -o json)
DEPLOYMENT_ID=$(echo "$DEPLOYMENT" | jq -r '.id')
echo "Deployment ID: $DEPLOYMENT_ID"
# Wait for deployment to start
sleep 5
# Monitor deployment progress
MAX_ATTEMPTS=180
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
STATUS=$(teenode deployment describe "$DEPLOYMENT_ID" -o json | jq -r '.status')
echo "Status: $STATUS"
case $STATUS in
BUILDING)
echo " Building application..."
;;
DEPLOYING)
echo " Deploying to infrastructure..."
;;
RUNNING)
echo " ✓ Deployment completed"
break
;;
FAILED)
echo " ✗ Deployment failed"
teenode deployment logs "$DEPLOYMENT_ID"
exit 1
;;
esac
sleep 10
((ATTEMPT++))
done
# Health check
echo "Performing health check..."
sleep 5
HEALTH=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_CHECK_URL")
if [ "$HEALTH" = "200" ]; then
echo "✓ Application is healthy"
else
echo "✗ Health check failed (HTTP $HEALTH)"
exit 1
fi
echo "✓ Deployment complete and verified"Cost Analysis Workflow
Analyze and report on resource usage:
#!/bin/bash
# cost-analysis.sh
echo "Resource Usage and Cost Analysis"
echo "=================================="
# Get all VMs
TOTAL_COST=0
TOTAL_CPU=0
TOTAL_MEMORY=0
echo ""
echo "Virtual Machines:"
echo "Name | CPU | Memory | Monthly Cost"
echo "---------------------------------------------------"
teenode vm list -o json | jq -r '.[] | \
"\(.name),\(.cpu),\(.memory)"' | \
while IFS=',' read -r name cpu memory; do
# Estimate cost (example pricing)
CPU_COST=$(echo "$cpu * 0.10" | bc) # $0.10 per CPU per day
MEMORY_COST=$(echo "$memory / 1024 * 0.05" | bc) # $0.05 per GB per day
DAILY_COST=$(echo "$CPU_COST + $MEMORY_COST" | bc)
MONTHLY_COST=$(echo "$DAILY_COST * 30" | bc)
printf "%-20s | %3s | %5dM | $%8.2f
" "$name" "$cpu" "$memory" "$MONTHLY_COST"
TOTAL_COST=$(echo "$TOTAL_COST + $MONTHLY_COST" | bc)
done
# Get all projects and deployments
echo ""
echo "Deployments:"
echo "Project | Deployments | Storage"
echo "---------------------------------------------------"
teenode project list -o json | jq -r '.[] | .name' | \
while read -r project; do
COUNT=$(teenode deployment list "$project" -o json | jq 'length')
STORAGE=$(teenode project info "$project" -o json | jq -r '.storage // 0')
# Storage cost
STORAGE_COST=$(echo "$STORAGE * 0.03 * 30" | bc)
TOTAL_COST=$(echo "$TOTAL_COST + $STORAGE_COST" | bc)
printf "%-20s | %11d | %6dGB
" "$project" "$COUNT" "$STORAGE"
done
echo ""
echo "---------------------------------------------------"
echo "Estimated Monthly Cost: $$(echo "scale=2; $TOTAL_COST" | bc)"
echo "✓ Cost analysis complete"Disaster Recovery Workflow
Complete DR procedure with snapshots:
#!/bin/bash
# disaster-recovery.sh
SOURCE_VM="$1"
TARGET_VM="$2-recovered-$(date +%s)"
if [ -z "\$SOURCE_VM" ] || [ -z "\$TARGET_VM" ]; then
echo "Usage: $0 <source-vm> <prefix>"
echo "Example: $0 prod-db db"
exit 1
fi
echo "Starting disaster recovery..."
echo "Source: \$SOURCE_VM"
echo "Target: \$TARGET_VM"
# Create snapshot if not restoring from existing
read -p "Restore from snapshot? (y/n) " RESTORE
if [ "$RESTORE" = "y" ]; then
echo "Available snapshots:"
teenode vm snapshot list "\$SOURCE_VM" | nl
read -p "Snapshot number: " SNAPSHOT_NUM
SNAPSHOT=$(teenode vm snapshot list "\$SOURCE_VM" | sed -n "\$SNAPSHOT_NUM p" | awk '{print $1}')
echo "Using snapshot: \$SNAPSHOT"
else
echo "Creating fresh snapshot..."
SNAPSHOT="\$SOURCE_VM-recovery-$(date +%Y%m%d-%H%M%S)"
teenode vm snapshot create "\$SOURCE_VM" --name "\$SNAPSHOT"
fi
# Create new VM from snapshot
echo "Creating new VM from snapshot..."
teenode vm create-from-snapshot \
--name "\$TARGET_VM" \
--snapshot "\$SNAPSHOT" \
--region us-east \
--wait
echo "✓ New VM created: \$TARGET_VM"
# Verify data integrity
echo "Verifying data integrity..."
TARGET_IP=$(teenode vm describe "\$TARGET_VM" | grep "IP Address" | awk '{print $NF}')
ssh -i ~/.ssh/id_ed25519 root@$TARGET_IP "\
echo 'Checking filesystems...' && \
df -h && \
echo 'Checking services...' && \
systemctl status"
echo "✓ Disaster recovery complete"
echo "New VM: \$TARGET_VM ($TARGET_IP)"
# Optional: Delete source
read -p "Delete source VM? (y/n) " DELETE
if [ "$DELETE" = "y" ]; then
teenode vm delete "\$SOURCE_VM"
echo "✓ Source VM deleted"
fiAudit and Compliance Workflow
Generate compliance audit trail:
#!/bin/bash
# compliance-audit.sh
REPORT_DATE=$(date +%Y-%m-%d)
REPORT_FILE="compliance-audit-$REPORT_DATE.json"
echo "Generating compliance audit report..."
# Initialize report
cat > "$REPORT_FILE" << 'EOF'
{
"report_date": "'"$REPORT_DATE"'",
"timestamp": "'"$(date -Iseconds)"'",
"vms": [],
"projects": [],
"security_findings": []
}
EOF
# Check all VMs for security settings
echo "Checking VM security settings..."
teenode vm list -o json | jq -r '.[] | .name' | \
while read -r vm; do
# Get attestation
ATTESTATION=$(teenode vm attest "$vm" --output /dev/stdout 2>/dev/null)
DEBUG=$(echo "$ATTESTATION" | jq '.report.policy.debug_allowed')
# Create VM report
VM_REPORT=$(jq -n \
--arg name "$vm" \
--argjson debug "$DEBUG" \
'{
name: $name,
debug_allowed: $debug,
checked_at: "'$(date -Iseconds)'"
}')
jq ".vms += [$VM_REPORT]" "$REPORT_FILE" > "$REPORT_FILE.tmp"
mv "$REPORT_FILE.tmp" "$REPORT_FILE"
if [ "$DEBUG" = "true" ]; then
FINDING=$(jq -n --arg vm "$vm" \
'{
severity: "high",
finding: "Debug mode enabled",
vm: $vm,
recommendation: "Disable debug mode for production"
}')
jq ".security_findings += [$FINDING]" "$REPORT_FILE" > "$REPORT_FILE.tmp"
mv "$REPORT_FILE.tmp" "$REPORT_FILE"
fi
done
# Check project configurations
echo "Checking project configurations..."
teenode project list -o json | jq '.[] | .' | \
while read -r project; do
PROJECT_NAME=$(echo "$project" | jq -r '.name')
PROJECT_REPORT=$(echo "$project" | jq '{
name: .name,
auto_deploy: .auto_deploy_enabled,
created_at: .created_at
}')
jq ".projects += [$PROJECT_REPORT]" "$REPORT_FILE" > "$REPORT_FILE.tmp"
mv "$REPORT_FILE.tmp" "$REPORT_FILE"
done
echo "✓ Report generated: $REPORT_FILE"
# Display summary
echo ""
echo "Audit Summary:"
jq '{
total_vms: (.vms | length),
total_projects: (.projects | length),
security_findings: (.security_findings | length),
debug_enabled_vms: [.vms[] | select(.debug_allowed == true) | .name]
}' "$REPORT_FILE"CI/CD Integration Workflow
Automated deployment from Git push:
#!/bin/bash
# ci-cd-webhook-handler.sh
# Handle webhook from GitHub/GitLab for auto-deployment
# Parse webhook payload
PUSH_EVENT=$(echo "$1" | jq '.push_event')
BRANCH=$(echo "$PUSH_EVENT" | jq -r '.ref' | sed 's|refs/heads/||')
COMMIT=$(echo "$PUSH_EVENT" | jq -r '.after')
PROJECT=$(echo "$PUSH_EVENT" | jq -r '.repository.name')
if [ "$BRANCH" != "main" ]; then
echo "Not main branch, skipping deployment"
exit 0
fi
echo "Webhook received for $PROJECT:$BRANCH"
echo "Commit: $COMMIT"
# Verify commit is signed (optional)
# git verify-commit $COMMIT || exit 1
# Build artifact
echo "Building..."
docker build -t $PROJECT:$COMMIT .
if [ $? -ne 0 ]; then
echo "Build failed"
exit 1
fi
# Push to registry
docker push $PROJECT:$COMMIT
# Deploy to Teenode
echo "Deploying..."
teenode deployment create "$PROJECT" \
--branch "$BRANCH" \
--image "$PROJECT:$COMMIT"
# Wait for deployment
sleep 30
DEPLOYMENT_ID=$(teenode deployment list "$PROJECT" --limit 1 | head -1)
# Verify health
HEALTH=$(curl -s -o /dev/null -w "%{http_code}" "https://$PROJECT.teenode.app/health")
if [ "$HEALTH" = "200" ]; then
echo "✓ Deployment successful"
else
echo "✗ Deployment failed health check"
exit 1
fiFleet Management Workflow
Manage multiple VMs as a fleet:
#!/bin/bash
# fleet-manager.sh
FLEET_NAME="$1"
COMMAND="$2"
if [ -z "$FLEET_NAME" ] || [ -z "$COMMAND" ]; then
echo "Usage: $0 <fleet-name> <command>"
echo "Commands: status, restart, update, scale"
exit 1
fi
# Get all VMs in fleet
VMS=$(teenode vm list --tags "fleet=$FLEET_NAME" -o json | jq -r '.[].name')
case $COMMAND in
status)
echo "Fleet: $FLEET_NAME"
for vm in $VMS; do
STATUS=$(teenode vm describe "$vm" | grep "Status:" | awk '{print $NF}')
echo " $vm: $STATUS"
done
;;
restart)
echo "Restarting fleet: $FLEET_NAME"
for vm in $VMS; do
echo " Restarting $vm..."
teenode vm stop "$vm" --wait
teenode vm start "$vm" --wait
done
echo "✓ Fleet restarted"
;;
update)
echo "Updating fleet: $FLEET_NAME"
for vm in $VMS; do
echo " Updating $vm..."
ssh root@$(teenode vm describe "$vm" | grep "IP Address" | awk '{print $NF}') \
"apt update && apt upgrade -y"
done
echo "✓ Fleet updated"
;;
scale)
read -p "Scale to how many nodes? " COUNT
CURRENT=$(echo "$VMS" | wc -l)
if [ $COUNT -gt $CURRENT ]; then
echo "Adding $((COUNT - CURRENT)) nodes..."
for i in $(seq $((CURRENT + 1)) $COUNT); do
teenode vm create \
--name "$FLEET_NAME-node-$i" \
--tags "fleet=$FLEET_NAME"
done
elif [ $COUNT -lt $CURRENT ]; then
echo "Removing $((CURRENT - COUNT)) nodes..."
echo "$VMS" | tail -n $((CURRENT - COUNT)) | \
while read -r vm; do
teenode vm delete "$vm"
done
fi
;;
*)
echo "Unknown command: $COMMAND"
exit 1
;;
esacTips for Production Scripts
- Always use error checking (
set -eor check exit codes) - Log operations with timestamps for auditing
- Include rollback procedures for failed deployments
- Use retry logic for transient failures
- Set appropriate timeouts for long operations
- Test scripts in staging before running in production
- Store scripts in version control
- Use systemd or cron for scheduled tasks
Next Steps
These workflows can be customized and combined for your specific use cases. Start with simpler workflows and gradually automate more complex processes.