SDK Examples

Practical code examples and recipes for common Noid SDK use cases.

Basic VM Lifecycle

Create, use, and destroy a VM:

import { NoidClient } from '@noid/sdk';

const client = new NoidClient({
  serverUrl: 'http://localhost:7654',
  token: process.env.NOID_TOKEN!,
});

async function basicLifecycle() {
  // Create VM
  const vm = await client.createVM({
    name: 'demo-vm',
    vcpus: 2,
    memory: 2048,
  });
  console.log(`✓ Created: ${vm.name}`);

  // Execute command
  const result = await client.exec(vm.name, 'echo "Hello from VM"');
  console.log(`Output: ${result.stdout}`);

  // Destroy VM
  await client.destroyVM(vm.name);
  console.log(`✓ Destroyed: ${vm.name}`);
}

basicLifecycle();

Golden Snapshot Pattern

Create a configured VM once, then clone it multiple times:

async function goldenSnapshot() {
  const baseVM = 'base-vm';

  // Create and configure base VM
  await client.createVM({ name: baseVM });
  await client.exec(baseVM, 'apt-get update -y');
  await client.exec(baseVM, 'apt-get install -y nodejs npm python3');

  // Create golden checkpoint
  await client.createCheckpoint(baseVM, 'golden', {
    label: 'Fully configured development environment',
  });
  console.log('✓ Golden checkpoint created');

  // Create multiple clones from checkpoint
  const workers = ['worker-1', 'worker-2', 'worker-3'];
  for (const worker of workers) {
    await client.restore(baseVM, 'golden', { as: worker });
    console.log(`✓ Created ${worker} from golden snapshot`);
  }

  // Each worker now has Node.js, npm, and Python pre-installed
  const vms = await client.listVMs();
  console.log(`Total VMs: ${vms.length}`);
}

Parallel Task Execution

Run tasks in parallel across multiple VMs:

async function parallelExecution() {
  const tasks = [
    { name: 'task-1', command: 'python compute.py --input data1.csv' },
    { name: 'task-2', command: 'python compute.py --input data2.csv' },
    { name: 'task-3', command: 'python compute.py --input data3.csv' },
  ];

  // Create VMs in parallel
  const vmPromises = tasks.map(task =>
    client.createVM({ name: task.name, vcpus: 4, memory: 4096 })
  );
  await Promise.all(vmPromises);
  console.log('✓ All VMs created');

  // Execute tasks in parallel
  const execPromises = tasks.map(task =>
    client.exec(task.name, task.command)
  );
  const results = await Promise.all(execPromises);

  // Process results
  results.forEach((result, idx) => {
    console.log(`Task ${idx + 1} completed with exit code ${result.exitCode}`);
  });

  // Cleanup
  await Promise.all(tasks.map(task => client.destroyVM(task.name)));
}

Testing with Checkpoints

Use checkpoints to reset test environments:

async function testingWorkflow() {
  const testVM = 'test-env';

  // Create and setup test VM
  await client.createVM({ name: testVM });
  await client.exec(testVM, 'apt-get update && apt-get install -y nodejs npm');
  await client.exec(testVM, 'git clone https://github.com/user/app.git /app');

  // Create clean state checkpoint
  await client.createCheckpoint(testVM, 'clean', {
    label: 'Clean test environment with app installed',
  });

  // Run test suite 1
  await client.exec(testVM, 'cd /app && npm test -- suite1');

  // Reset to clean state
  await client.restore(testVM, 'clean');

  // Run test suite 2
  await client.exec(testVM, 'cd /app && npm test -- suite2');

  // Reset again
  await client.restore(testVM, 'clean');

  console.log('✓ All test suites completed with clean environments');
}

CI/CD Integration

Integrate Noid into your CI/CD pipeline:

async function cicdPipeline() {
  const buildId = process.env.BUILD_ID || Date.now().toString();
  const vmName = `ci-${buildId}`;

  try {
    // Create isolated build environment
    console.log(`Creating build environment: ${vmName}`);
    await client.createVM({
      name: vmName,
      vcpus: 4,
      memory: 8192,
    });

    // Clone repository
    const repoUrl = process.env.REPO_URL!;
    await client.exec(vmName, `git clone ${repoUrl} /workspace`);

    // Install dependencies
    console.log('Installing dependencies...');
    await client.exec(vmName, 'cd /workspace && npm install');

    // Run tests
    console.log('Running tests...');
    const testResult = await client.exec(vmName, 'cd /workspace && npm test');

    if (testResult.exitCode !== 0) {
      throw new Error(`Tests failed: ${testResult.stderr}`);
    }

    // Build application
    console.log('Building application...');
    await client.exec(vmName, 'cd /workspace && npm run build');

    // Create artifact checkpoint
    await client.createCheckpoint(vmName, 'build-artifact', {
      label: `Build ${buildId} - ${new Date().toISOString()}`,
    });

    console.log('✓ Build completed successfully');
  } catch (error) {
    console.error('Build failed:', error);
    process.exit(1);
  } finally {
    // Cleanup
    await client.destroyVM(vmName).catch(console.error);
  }
}

Environment Variable Management

Manage environment variables for different configurations:

async function environmentConfigs() {
  const vm = 'app-vm';
  await client.createVM({ name: vm });

  // Development environment
  const devEnv = {
    NODE_ENV: 'development',
    DATABASE_URL: 'postgresql://localhost/dev_db',
    LOG_LEVEL: 'debug',
  };

  await client.exec(vm, 'node server.js', { env: devEnv });
  await client.createCheckpoint(vm, 'dev-config');

  // Production environment
  const prodEnv = {
    NODE_ENV: 'production',
    DATABASE_URL: 'postgresql://prod-server/prod_db',
    LOG_LEVEL: 'error',
  };

  await client.restore(vm, 'dev-config');
  await client.exec(vm, 'node server.js', { env: prodEnv });
}

Error Handling and Retries

Robust error handling with custom retry logic:

import { NoidError } from '@noid/sdk';

async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3,
  delay = 1000
): Promise<T> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (attempt === maxRetries) throw error;

      if (error instanceof NoidError && error.statusCode >= 500) {
        console.log(`Attempt ${attempt} failed, retrying...`);
        await new Promise(resolve => setTimeout(resolve, delay * attempt));
      } else {
        throw error; // Don't retry client errors
      }
    }
  }
  throw new Error('Max retries exceeded');
}

async function robustExecution() {
  const result = await withRetry(async () => {
    return await client.exec('my-vm', 'curl https://api.example.com/data');
  });

  console.log('Data retrieved:', result.stdout);
}

Resource Monitoring

Monitor VM resource usage:

async function monitorResources() {
  const vms = await client.listVMs();

  for (const vm of vms) {
    // Get CPU usage
    const cpuResult = await client.exec(
      vm.name,
      "top -bn1 | grep 'Cpu(s)' | awk '{print $2}'"
    );

    // Get memory usage
    const memResult = await client.exec(
      vm.name,
      "free -m | awk 'NR==2{printf \"%.2f\", $3*100/$2}'"
    );

    console.log(`${vm.name}:`);
    console.log(`  CPU: ${cpuResult.stdout.trim()}%`);
    console.log(`  Memory: ${memResult.stdout.trim()}%`);
  }
}

// Run monitoring every 30 seconds
setInterval(monitorResources, 30000);

Batch Operations

Perform operations on multiple VMs:

async function batchOperations() {
  const vmNames = ['vm-1', 'vm-2', 'vm-3', 'vm-4', 'vm-5'];

  // Update all VMs
  console.log('Updating all VMs...');
  await Promise.all(
    vmNames.map(name =>
      client.exec(name, 'apt-get update && apt-get upgrade -y')
    )
  );

  // Create checkpoints for all VMs
  console.log('Creating checkpoints...');
  await Promise.all(
    vmNames.map(name =>
      client.createCheckpoint(name, 'post-update', {
        label: `Updated on ${new Date().toISOString()}`,
      })
    )
  );

  console.log('✓ Batch operations completed');
}

Next Steps