Skip to main content
Glama
danielbodnar

VyOS MCP Server

by danielbodnar
container-manager.ts6.9 kB
/** * @fileoverview Container management utilities for VyOS MCP testing * * This module provides utilities for managing VyOS and MCP server containers * during integration testing, using testcontainers for container lifecycle * management. * * @author VyOS MCP Server Tests * @version 1.0.0 * @since 2025-07-12 */ import { GenericContainer, StartedTestContainer, Wait } from 'testcontainers'; import { VyOSClient } from '../../src/vyos-client'; export interface ContainerTestConfig { vyosApiKey: string; networkName: string; vyosImage: string; mcpImage?: string; timeout: number; } export interface StartedContainers { vyosContainer: StartedTestContainer; mcpContainer?: StartedTestContainer; networkName: string; vyosClient: VyOSClient; cleanup: () => Promise<void>; } export class VyOSContainerManager { private config: ContainerTestConfig; private containers: StartedTestContainer[] = []; constructor(config: Partial<ContainerTestConfig> = {}) { this.config = { vyosApiKey: 'vyos-mcp-test-key', networkName: 'vyos-test-network', // Note: vyos/vyos-build:current is a build environment, not runtime VyOS // For proper testing, build a runtime image with scripts/build-vyos-image.sh vyosImage: 'docker.io/vyos/vyos-build:current', timeout: 120000, // 2 minutes ...config, }; } /** * Start VyOS container with API configuration */ async startVyOSContainer(): Promise<StartedTestContainer> { console.log('Starting VyOS container...'); // Warn if using build image if (this.config.vyosImage.includes('vyos-build')) { console.warn('⚠️ WARNING: Using vyos/vyos-build:current (build environment)'); console.warn(' For proper VyOS API testing, build a runtime image:'); console.warn(' sudo ./scripts/build-vyos-image.sh'); console.warn(' Then update tests to use: vyos-runtime:1.4-rolling-*'); } const container = await new GenericContainer(this.config.vyosImage) .withPrivilegedMode() .withExposedPorts(22, 443) .withEnvironment({ VYOS_API_KEY: this.config.vyosApiKey, }) .withWaitStrategy( Wait.forAll([ Wait.forListeningPorts(), // For build image, just wait for container to be running Wait.forLogMessage(/.*/, 1, 30000), ]) ) .withStartupTimeout(this.config.timeout) .withEntrypoint([ 'sh', '-c', `if [ -x /sbin/init ]; then /sbin/init & else sleep infinity & fi; wait` ]) .start(); this.containers.push(container); // Wait a bit more for VyOS to fully initialize await this.sleep(10000); // Configure VyOS via CLI commands await this.configureVyOS(container); return container; } /** * Configure VyOS instance with API access */ private async configureVyOS(container: StartedTestContainer): Promise<void> { console.log('Configuring VyOS API...'); const commands = [ // Enter configuration mode '/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper begin', // Configure system "/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper set system host-name 'vyos-test'", // Configure API `/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper set service https api keys id vyos-mcp key '${this.config.vyosApiKey}'`, '/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper set service https port 443', "/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper set service https api cors allow-origin '*'", // Commit and save '/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper commit', '/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper save', '/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper end', ]; for (const command of commands) { try { const result = await container.exec(command.split(' ')); if (result.exitCode !== 0) { console.warn(`Command failed: ${command}, exit code: ${result.exitCode}`); } } catch (error) { console.warn(`Error executing command: ${command}`, error); } } // Wait for API to be ready await this.sleep(5000); } /** * Create VyOS client for the container */ createVyOSClient(container: StartedTestContainer): VyOSClient { const host = container.getHost(); const port = container.getMappedPort(443); return new VyOSClient({ host: `https://${host}:${port}`, apiKey: this.config.vyosApiKey, timeout: 30000, verifySSL: false, }); } /** * Start all containers and return managed setup */ async startContainers(): Promise<StartedContainers> { const vyosContainer = await this.startVyOSContainer(); const vyosClient = this.createVyOSClient(vyosContainer); return { vyosContainer, networkName: this.config.networkName, vyosClient, cleanup: async () => { await this.cleanup(); }, }; } /** * Wait for VyOS API to be ready */ async waitForVyOSAPI(client: VyOSClient, maxRetries = 30): Promise<boolean> { console.log('Waiting for VyOS API to be ready...'); for (let i = 0; i < maxRetries; i++) { try { await client.getSystemInfo(); console.log('VyOS API is ready!'); return true; } catch (error) { console.log(`Waiting for API... attempt ${i + 1}/${maxRetries}`); await this.sleep(2000); } } console.error('VyOS API failed to become ready'); return false; } /** * Test VyOS API connectivity */ async testConnectivity(client: VyOSClient): Promise<boolean> { try { const info = await client.getSystemInfo(); console.log('VyOS connectivity test passed:', info); return true; } catch (error) { console.error('VyOS connectivity test failed:', error); return false; } } /** * Clean up all containers */ async cleanup(): Promise<void> { console.log('Cleaning up containers...'); for (const container of this.containers) { try { await container.stop(); } catch (error) { console.warn('Error stopping container:', error); } } this.containers = []; } /** * Utility function to sleep */ private sleep(ms: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); } } /** * Create a managed VyOS test environment */ export async function createVyOSTestEnvironment(config?: Partial<ContainerTestConfig>): Promise<StartedContainers> { const manager = new VyOSContainerManager(config); const containers = await manager.startContainers(); // Wait for API to be ready const apiReady = await manager.waitForVyOSAPI(containers.vyosClient); if (!apiReady) { await containers.cleanup(); throw new Error('VyOS API failed to become ready'); } return containers; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/danielbodnar/vyos-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server