Skip to main content
Glama
danielbodnar

VyOS MCP Server

by danielbodnar
container-integration.test.ts12 kB
/** * @fileoverview Container-based integration tests for VyOS MCP server * * These tests run against real VyOS containers using testcontainers to ensure * complete end-to-end functionality. Tests cover: * - Real VyOS API interaction * - Container lifecycle management * - Network configuration scenarios * - Error handling with real systems * - Performance with actual VyOS instances * * @author VyOS MCP Server Tests * @version 1.0.0 * @since 2025-07-12 */ import { describe, expect, it, beforeAll, afterAll } from 'bun:test'; import { createVyOSTestEnvironment, type StartedContainers } from './utils/container-manager'; import { VyOSClient } from '../src/vyos-client'; describe('VyOS MCP Container Integration Tests', () => { let testEnv: StartedContainers; let vyosClient: VyOSClient; // Extended timeout for container operations const CONTAINER_TIMEOUT = 300000; // 5 minutes beforeAll(async () => { console.log('Setting up VyOS test environment...'); testEnv = await createVyOSTestEnvironment({ vyosApiKey: 'container-test-key-123', timeout: CONTAINER_TIMEOUT, }); vyosClient = testEnv.vyosClient; console.log('VyOS test environment ready!'); }, CONTAINER_TIMEOUT); afterAll(async () => { if (testEnv) { console.log('Cleaning up test environment...'); await testEnv.cleanup(); } }); describe('Container Setup and Connectivity', () => { it('should connect to VyOS container successfully', async () => { expect(testEnv.vyosContainer).toBeDefined(); expect(vyosClient).toBeDefined(); }); it('should retrieve VyOS system information', async () => { const systemInfo = await vyosClient.getSystemInfo(); expect(systemInfo).toBeDefined(); expect(typeof systemInfo).toBe('object'); }); it('should get VyOS version information', async () => { const version = await vyosClient.getVersion(); expect(version).toBeDefined(); expect(typeof version).toBe('object'); }); }); describe('Configuration Management with Real VyOS', () => { it('should show current configuration', async () => { const config = await vyosClient.showConfig(); expect(config).toBeDefined(); expect(typeof config).toBe('object'); }); it('should show specific configuration path', async () => { const systemConfig = await vyosClient.showConfig(['system']); expect(systemConfig).toBeDefined(); expect(typeof systemConfig).toBe('object'); }); it('should set and commit configuration changes', async () => { // Set a test configuration await vyosClient.setConfig( ['system', 'domain-name'], 'container-test.local' ); // Commit the change await vyosClient.commit('Container test configuration'); // Verify the change const domainConfig = await vyosClient.showConfig(['system', 'domain-name']); expect(domainConfig).toBeDefined(); }); it('should delete configuration and commit', async () => { // First set a test value await vyosClient.setConfig( ['system', 'domain-search', 'domain', 'test.local'], null ); await vyosClient.commit('Add test domain search'); // Then delete it await vyosClient.deleteConfig(['system', 'domain-search', 'domain', 'test.local']); await vyosClient.commit('Remove test domain search'); // Verify it's gone const exists = await vyosClient.configExists(['system', 'domain-search', 'domain', 'test.local']); expect(exists).toBe(false); }); it('should save configuration to startup config', async () => { await vyosClient.save(); // If this doesn't throw, the save was successful }); }); describe('Interface Configuration', () => { it('should list available interfaces', async () => { const interfaces = await vyosClient.getInterfaces(); expect(interfaces).toBeDefined(); expect(typeof interfaces).toBe('object'); }); it('should configure a loopback interface', async () => { // Create loopback interface await vyosClient.setConfig( ['interfaces', 'loopback', 'lo100', 'address'], '10.100.100.1/32' ); await vyosClient.setConfig( ['interfaces', 'loopback', 'lo100', 'description'], 'Container test loopback' ); await vyosClient.commit('Add container test loopback interface'); // Verify the interface configuration const loopbackConfig = await vyosClient.showConfig(['interfaces', 'loopback', 'lo100']); expect(loopbackConfig).toBeDefined(); // Check if the interface exists in the interface list const interfaces = await vyosClient.getInterfaces(); expect(interfaces).toBeDefined(); }); it('should get interface statistics', async () => { const stats = await vyosClient.getInterfaceStatistics(); expect(stats).toBeDefined(); expect(typeof stats).toBe('object'); }); }); describe('Routing Configuration', () => { it('should show current routing table', async () => { const routes = await vyosClient.getRoutes(); expect(routes).toBeDefined(); }); it('should configure static routes', async () => { // Add a static route await vyosClient.setConfig( ['protocols', 'static', 'route', '192.168.200.0/24', 'next-hop'], '10.100.100.1' ); await vyosClient.setConfig( ['protocols', 'static', 'route', '192.168.200.0/24', 'description'], 'Container test route' ); await vyosClient.commit('Add container test static route'); // Verify the route configuration const routeConfig = await vyosClient.showConfig(['protocols', 'static']); expect(routeConfig).toBeDefined(); }); }); describe('Operational Commands', () => { it('should execute show commands', async () => { const result = await vyosClient.showOperational(['version']); expect(result).toBeDefined(); }); it('should execute show interfaces command', async () => { const result = await vyosClient.showOperational(['interfaces']); expect(result).toBeDefined(); }); it('should execute show ip route command', async () => { const result = await vyosClient.showOperational(['ip', 'route']); expect(result).toBeDefined(); }); }); describe('Network Diagnostics', () => { it('should ping localhost successfully', async () => { const pingResult = await vyosClient.ping('127.0.0.1', { count: 3, timeout: 5, }); expect(pingResult).toBeDefined(); expect(typeof pingResult).toBe('object'); }); it('should ping container gateway', async () => { // Try to ping the container gateway const pingResult = await vyosClient.ping('172.17.0.1', { count: 2, timeout: 10, }); expect(pingResult).toBeDefined(); }); it('should execute traceroute to localhost', async () => { const traceResult = await vyosClient.traceroute('127.0.0.1', { maxHops: 5, }); expect(traceResult).toBeDefined(); expect(typeof traceResult).toBe('object'); }); }); describe('System Management', () => { it('should get system uptime', async () => { const uptime = await vyosClient.getUptime(); expect(uptime).toBeDefined(); }); it('should get system resources', async () => { const resources = await vyosClient.getSystemResources(); expect(resources).toBeDefined(); expect(typeof resources).toBe('object'); }); it('should get system memory information', async () => { const memory = await vyosClient.getSystemMemory(); expect(memory).toBeDefined(); expect(typeof memory).toBe('object'); }); it('should get system storage information', async () => { const storage = await vyosClient.getSystemStorage(); expect(storage).toBeDefined(); expect(typeof storage).toBe('object'); }); }); describe('Error Handling with Real System', () => { it('should handle invalid configuration paths gracefully', async () => { await expect( vyosClient.showConfig(['invalid', 'configuration', 'path']) ).rejects.toThrow(); }); it('should handle invalid set operations gracefully', async () => { await expect( vyosClient.setConfig(['invalid', 'config', 'path'], 'test-value') ).rejects.toThrow(); }); it('should handle invalid operational commands gracefully', async () => { await expect( vyosClient.showOperational(['invalid', 'command']) ).rejects.toThrow(); }); it('should handle unreachable ping targets gracefully', async () => { // Try to ping an unreachable address const pingResult = await vyosClient.ping('192.168.255.255', { count: 1, timeout: 2, }); // Should not throw, but may return failure information expect(pingResult).toBeDefined(); }); }); describe('Configuration Workflows', () => { it('should complete a full interface configuration workflow', async () => { const interfaceName = 'lo200'; const interfaceIP = '10.200.200.1/32'; const description = 'Full workflow test interface'; // Step 1: Configure interface await vyosClient.setConfig( ['interfaces', 'loopback', interfaceName, 'address'], interfaceIP ); await vyosClient.setConfig( ['interfaces', 'loopback', interfaceName, 'description'], description ); // Step 2: Commit configuration await vyosClient.commit('Full workflow interface configuration'); // Step 3: Verify configuration const config = await vyosClient.showConfig(['interfaces', 'loopback', interfaceName]); expect(config).toBeDefined(); // Step 4: Save configuration await vyosClient.save(); // Step 5: Verify interface is active const interfaces = await vyosClient.getInterfaces(); expect(interfaces).toBeDefined(); }); it('should handle configuration rollback scenario', async () => { // Make a configuration change await vyosClient.setConfig( ['system', 'time-zone'], 'US/Pacific' ); // Commit with confirm (simulated by immediate rollback) await vyosClient.commit('Test timezone change'); // Rollback by setting different value await vyosClient.setConfig( ['system', 'time-zone'], 'UTC' ); await vyosClient.commit('Rollback timezone to UTC'); // Verify rollback const timezoneConfig = await vyosClient.showConfig(['system', 'time-zone']); expect(timezoneConfig).toBeDefined(); }); }); describe('Performance and Reliability', () => { it('should handle multiple concurrent operations', async () => { const operations = [ vyosClient.getSystemInfo(), vyosClient.getInterfaces(), vyosClient.getRoutes(), vyosClient.showConfig(['system']), vyosClient.getSystemResources(), ]; const results = await Promise.all(operations); // All operations should complete successfully for (const result of results) { expect(result).toBeDefined(); } }); it('should maintain configuration consistency across operations', async () => { const testValue = `container-test-${Date.now()}`; // Set a unique value await vyosClient.setConfig( ['system', 'host-name'], testValue ); await vyosClient.commit('Set test hostname'); // Read it back multiple times for (let i = 0; i < 5; i++) { const config = await vyosClient.showConfig(['system', 'host-name']); expect(config).toBeDefined(); } }); }); }); // Set timeout for the entire test suite process.env.BUN_TEST_TIMEOUT = String(CONTAINER_TIMEOUT);

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