# Komodo Write Module - Usage Examples
This document provides practical examples for using the Write module functions.
## Setup
```typescript
import {
createServer,
updateServer,
deleteServer,
createDeployment,
createStack,
createBuild,
createRepo,
createProcedure,
createAction,
} from './src/modules/index.js';
```
## Server Management
### Create a Production Server
```typescript
const server = await createServer({
name: 'production-web-01',
address: '192.168.1.100',
port: 22,
region: 'us-east-1',
provider: 'aws',
tags: ['production', 'web', 'high-availability'],
enabled: true,
metadata: {
instanceType: 't3.large',
volumes: ['/dev/sda1'],
securityGroups: ['sg-12345']
}
});
console.log(`Created server: ${server.data.id}`);
```
### Update Server Configuration
```typescript
const updated = await updateServer('server-123', {
tags: ['production', 'web', 'high-availability', 'maintenance'],
enabled: false,
metadata: {
maintenanceWindow: '2024-01-27T02:00:00Z',
reason: 'Security patches'
}
});
```
### Delete a Server
```typescript
const result = await deleteServer('server-old-123');
if (result.data.success) {
console.log('Server deleted:', result.data.deletedId);
}
```
## Deployment Workflows
### Deploy a Node.js Application
```typescript
const deployment = await createDeployment({
name: 'api-service-v2',
serverId: 'server-123',
image: 'mycompany/api:2.0.0',
environment: {
NODE_ENV: 'production',
PORT: '3000',
DATABASE_URL: 'postgresql://db:5432/myapp',
REDIS_URL: 'redis://cache:6379',
API_KEY: process.env.API_KEY
},
ports: [
{ host: 80, container: 3000 }
],
volumes: [
'/app/logs:/var/log/app',
'/app/data:/data'
],
networks: ['app-network'],
restart: 'unless-stopped',
enabled: true,
metadata: {
version: '2.0.0',
deployedBy: 'ci-cd-pipeline',
buildNumber: '456'
}
});
```
### Update Deployment Image
```typescript
const updated = await updateDeployment('deploy-456', {
image: 'mycompany/api:2.1.0',
metadata: {
version: '2.1.0',
deployedBy: 'manual',
buildNumber: '457',
rollbackImage: 'mycompany/api:2.0.0'
}
});
```
## Stack Management
### Create a Monitoring Stack
```typescript
const composeFile = `
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
volumes:
- prometheus-data:/prometheus
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
networks:
- monitoring
grafana:
image: grafana/grafana:latest
volumes:
- grafana-data:/var/lib/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=\${GRAFANA_PASSWORD}
networks:
- monitoring
alertmanager:
image: prom/alertmanager:latest
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
ports:
- "9093:9093"
networks:
- monitoring
volumes:
prometheus-data:
grafana-data:
networks:
monitoring:
driver: bridge
`;
const stack = await createStack({
name: 'monitoring-stack',
composeFile: composeFile,
projectName: 'monitoring',
environment: {
GRAFANA_PASSWORD: process.env.GRAFANA_PASSWORD
},
enabled: true,
metadata: {
purpose: 'System monitoring and alerting',
maintainer: 'devops-team'
}
});
```
## Build Configurations
### Create a Multi-Stage Build
```typescript
const build = await createBuild({
name: 'api-optimized-build',
repoId: 'repo-789',
dockerfile: './Dockerfile.production',
context: '.',
buildArgs: {
NODE_VERSION: '18-alpine',
BUILD_ENV: 'production',
ENABLE_CACHE: 'true'
},
target: 'production',
tags: ['latest', 'v2.0.0', 'stable'],
enabled: true,
metadata: {
buildStrategy: 'multi-stage',
optimization: 'size-optimized',
targetSize: '< 100MB'
}
});
```
## Repository Management
### Add a GitHub Repository with SSH
```typescript
const repo = await createRepo({
name: 'company-api',
url: 'git@github.com:mycompany/api.git',
branch: 'main',
credentials: {
sshKey: process.env.GITHUB_SSH_KEY
},
autoSync: true,
webhookSecret: process.env.GITHUB_WEBHOOK_SECRET,
enabled: true,
metadata: {
owner: 'mycompany',
visibility: 'private',
primaryLanguage: 'TypeScript'
}
});
```
### Add a Public Repository with HTTPS
```typescript
const publicRepo = await createRepo({
name: 'open-source-tool',
url: 'https://github.com/opensource/tool.git',
branch: 'develop',
autoSync: false,
enabled: true,
metadata: {
license: 'MIT',
stars: 1500
}
});
```
## Automated Procedures
### Database Backup Procedure
```typescript
const backupProcedure = await createProcedure({
name: 'database-backup',
description: 'Automated database backup and upload to S3',
steps: [
{
type: 'command',
command: 'pg_dump -U postgres myapp > /tmp/backup.sql',
timeout: 300000, // 5 minutes
continueOnError: false
},
{
type: 'command',
command: 'gzip /tmp/backup.sql',
timeout: 60000,
continueOnError: false
},
{
type: 'script',
script: `#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
aws s3 cp /tmp/backup.sql.gz s3://backups/db/backup_$DATE.sql.gz
rm /tmp/backup.sql.gz`,
timeout: 300000,
continueOnError: false
},
{
type: 'api-call',
apiEndpoint: 'https://api.slack.com/notify',
timeout: 5000,
continueOnError: true
}
],
schedule: '0 2 * * *', // Daily at 2 AM
enabled: true,
metadata: {
retention: '30 days',
priority: 'critical'
}
});
```
### Deployment Health Check
```typescript
const healthCheck = await createProcedure({
name: 'deployment-health-check',
description: 'Check health of all deployments',
steps: [
{
type: 'api-call',
apiEndpoint: 'https://api.example.com/health',
timeout: 10000,
continueOnError: true
},
{
type: 'script',
script: `#!/bin/bash
if [ $? -eq 0 ]; then
echo "Health check passed"
exit 0
else
echo "Health check failed - initiating recovery"
docker restart api-service
exit 1
fi`,
timeout: 30000,
continueOnError: false
}
],
schedule: '*/5 * * * *', // Every 5 minutes
enabled: true
});
```
## Automated Actions
### Auto-Deploy on Git Push
```typescript
const autoDeploy = await createAction({
name: 'auto-deploy-production',
description: 'Deploy to production when main branch is updated',
trigger: {
type: 'webhook',
webhookSecret: process.env.WEBHOOK_SECRET
},
action: {
type: 'procedure',
targetId: 'deploy-procedure-123',
parameters: {
environment: 'production',
runTests: true,
notifySlack: true
}
},
enabled: true,
metadata: {
repository: 'company-api',
branch: 'main'
}
});
```
### Scheduled Build
```typescript
const nightlyBuild = await createAction({
name: 'nightly-build',
description: 'Build and test application every night',
trigger: {
type: 'schedule',
schedule: '0 0 * * *' // Daily at midnight
},
action: {
type: 'build',
targetId: 'build-789',
parameters: {
cleanBuild: true,
runTests: true,
publishArtifacts: true
}
},
enabled: true
});
```
### Manual Recovery Action
```typescript
const recovery = await createAction({
name: 'emergency-recovery',
description: 'Manual action to recover failed deployments',
trigger: {
type: 'manual'
},
action: {
type: 'command',
command: 'docker-compose down && docker-compose up -d',
parameters: {
timeout: 120000,
notifyOnCompletion: true
}
},
enabled: true,
metadata: {
severity: 'critical',
requiresApproval: true
}
});
```
## Error Handling
### Comprehensive Error Handling
```typescript
import { ValidationError } from './src/utils/validation.js';
async function deployApplication() {
try {
// Create repository
const repo = await createRepo({
name: 'my-app',
url: 'https://github.com/me/app.git',
branch: 'main'
});
// Create build
const build = await createBuild({
name: 'app-build',
repoId: repo.data.id,
dockerfile: './Dockerfile'
});
// Create deployment
const deployment = await createDeployment({
name: 'app-deployment',
serverId: 'server-123',
image: 'myapp:latest'
});
console.log('Deployment successful:', deployment.data.id);
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation failed:', error.message);
// Handle validation error
} else if (error.statusCode === 404) {
console.error('Resource not found');
// Handle 404
} else if (error.statusCode === 401) {
console.error('Authentication failed');
// Handle auth error
} else {
console.error('Unexpected error:', error.message);
// Handle other errors
}
}
}
```
## Batch Operations
### Create Multiple Resources
```typescript
async function setupInfrastructure() {
// Create servers
const servers = await Promise.all([
createServer({
name: 'web-01',
address: '192.168.1.101',
tags: ['web']
}),
createServer({
name: 'web-02',
address: '192.168.1.102',
tags: ['web']
}),
createServer({
name: 'db-01',
address: '192.168.1.103',
tags: ['database']
})
]);
console.log(`Created ${servers.length} servers`);
// Create deployments on each web server
const deployments = await Promise.all(
servers
.filter(s => s.data.tags.includes('web'))
.map(server =>
createDeployment({
name: `api-on-${server.data.name}`,
serverId: server.data.id,
image: 'myapp:latest',
restart: 'always'
})
)
);
console.log(`Created ${deployments.length} deployments`);
}
```
## Update Patterns
### Conditional Updates
```typescript
async function updateIfNeeded(deploymentId: string) {
// Get current deployment (assume we have a read function)
// const current = await getDeployment(deploymentId);
// Update only if needed
const updates: any = {};
if (process.env.NEW_IMAGE) {
updates.image = process.env.NEW_IMAGE;
}
if (process.env.UPDATE_ENV === 'true') {
updates.environment = {
...updates.environment,
UPDATED_AT: new Date().toISOString()
};
}
if (Object.keys(updates).length > 0) {
await updateDeployment(deploymentId, updates);
console.log('Deployment updated');
} else {
console.log('No updates needed');
}
}
```
## Clean Up
### Delete with Confirmation
```typescript
async function cleanupOldResources(resourceIds: string[]) {
console.log(`About to delete ${resourceIds.length} resources`);
for (const id of resourceIds) {
try {
const result = await deleteServer(id);
console.log(`✓ Deleted: ${result.data.deletedId}`);
} catch (error) {
console.error(`✗ Failed to delete ${id}:`, error.message);
}
}
}
```
## Best Practices
### 1. Always Validate Before Creating
```typescript
function validateDeploymentConfig(config: any) {
if (!config.name || !config.serverId) {
throw new Error('Name and serverId are required');
}
if (config.ports && !Array.isArray(config.ports)) {
throw new Error('Ports must be an array');
}
return true;
}
const config = { name: 'app', serverId: 'server-123' };
if (validateDeploymentConfig(config)) {
await createDeployment(config);
}
```
### 2. Use Metadata for Tracking
```typescript
await createDeployment({
name: 'api-service',
serverId: 'server-123',
image: 'myapp:1.0.0',
metadata: {
deployedBy: process.env.USER,
deployedAt: new Date().toISOString(),
gitCommit: process.env.GIT_COMMIT,
buildNumber: process.env.BUILD_NUMBER,
environment: 'production'
}
});
```
### 3. Implement Retry Logic
```typescript
async function createWithRetry<T>(
fn: () => Promise<T>,
maxRetries = 3
): Promise<T> {
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
lastError = error;
console.log(`Attempt ${i + 1} failed, retrying...`);
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
throw lastError;
}
// Usage
const deployment = await createWithRetry(() =>
createDeployment({
name: 'api-service',
serverId: 'server-123',
image: 'myapp:latest'
})
);
```
### 4. Use Environment Variables for Secrets
```typescript
// DON'T: Hard-code secrets
const repo = await createRepo({
name: 'app',
url: 'https://github.com/me/app.git',
credentials: {
password: 'ghp_hardcoded123' // ❌ Bad
}
});
// DO: Use environment variables
const repo = await createRepo({
name: 'app',
url: 'https://github.com/me/app.git',
credentials: {
password: process.env.GITHUB_TOKEN // ✓ Good
}
});
```