Skip to main content
Glama
kubernetes-utils.ts13.8 kB
/** * Shared Kubernetes Utilities * * Common functions for interacting with Kubernetes clusters */ import { exec } from 'child_process'; import { promisify } from 'util'; import { withKubectlTracing } from './tracing'; const execAsync = promisify(exec); // Enhanced interfaces for kubectl-based discovery export interface KubectlConfig { context?: string; namespace?: string; kubeconfig?: string; timeout?: number; stdin?: string; // For piping input to kubectl (e.g., apply -f -) } /** * Execute kubectl command with proper configuration * Automatically traced with OpenTelemetry */ export async function executeKubectl(args: string[], config?: KubectlConfig): Promise<string> { // Wrap entire execution with tracing return withKubectlTracing(args, config, async () => { const command = buildKubectlCommand(args, config); const timeout = config?.timeout || 30000; try { // If stdin is provided, use spawn for proper stdin piping if (config?.stdin) { const { spawn } = require('child_process'); return new Promise((resolve, reject) => { let stdout = ''; let stderr = ''; const proc = spawn('sh', ['-c', command], { timeout, maxBuffer: 100 * 1024 * 1024 }); proc.stdout.on('data', (data: Buffer) => { stdout += data.toString(); }); proc.stderr.on('data', (data: Buffer) => { stderr += data.toString(); }); proc.on('error', (error: Error) => reject(error)); proc.on('close', (code: number) => { if (code !== 0) { reject(new Error(`kubectl command failed: ${stderr || stdout}`)); } else if (stderr && !stderr.includes('Warning') && !stderr.includes('No resources found')) { reject(new Error(`kubectl command failed: ${stderr}`)); } else { resolve(stdout.trim()); } }); // Write stdin and close proc.stdin.write(config.stdin); proc.stdin.end(); }); } // No stdin - use regular execAsync const { stdout, stderr } = await execAsync(command, { timeout, maxBuffer: 100 * 1024 * 1024 // 100MB buffer for large clusters with 1000+ CRDs }); if (stderr && !stderr.includes('Warning') && !stderr.includes('No resources found')) { throw new Error(`kubectl command failed: ${stderr}`); } return stdout.trim(); } catch (error: any) { if (error.code === 'ENOENT') { throw new Error('kubectl binary not found. Please install kubectl and ensure it\'s in your PATH.'); } // Use error classification for better error messages const classified = ErrorClassifier.classifyError(error); throw new Error(classified.enhancedMessage); } }); } /** * Build kubectl command string with proper flags */ /** * Safely escape shell arguments to prevent command injection */ function escapeShellArg(arg: string): string { if (!arg || typeof arg !== 'string') { return '""'; } // If the argument contains only safe characters, return as-is if (/^[a-zA-Z0-9._/-]+$/.test(arg)) { return arg; } // Otherwise, quote and escape return `"${arg.replace(/["\\]/g, '\\$&')}"`; } export function buildKubectlCommand(args: string[], config?: KubectlConfig): string { const cmdParts = ['kubectl']; if (config?.kubeconfig) { cmdParts.push('--kubeconfig', escapeShellArg(config.kubeconfig)); } if (config?.context) { cmdParts.push('--context', escapeShellArg(config.context)); } if (config?.namespace) { cmdParts.push('--namespace', escapeShellArg(config.namespace)); } // Safely add all arguments args.forEach(arg => cmdParts.push(escapeShellArg(arg))); return cmdParts.join(' '); } // Enhanced Error Classification System export class ErrorClassifier { static classifyError(error: Error): { type: string; enhancedMessage: string } { const originalMessage = error.message; // Connection and Network Errors if (this.isNetworkError(originalMessage)) { return { type: 'network', enhancedMessage: this.enhanceNetworkError(originalMessage) }; } // Authentication Errors if (this.isAuthenticationError(originalMessage)) { return { type: 'authentication', enhancedMessage: this.enhanceAuthenticationError(originalMessage) }; } // Authorization/RBAC Errors if (this.isAuthorizationError(originalMessage)) { return { type: 'authorization', enhancedMessage: this.enhanceAuthorizationError(originalMessage) }; } // API Availability Errors if (this.isAPIAvailabilityError(originalMessage)) { return { type: 'api-availability', enhancedMessage: this.enhanceAPIAvailabilityError(originalMessage) }; } // Kubeconfig Validation Errors if (this.isKubeconfigError(originalMessage)) { return { type: 'kubeconfig', enhancedMessage: this.enhanceKubeconfigError(originalMessage) }; } // Version Compatibility Errors if (this.isVersionCompatibilityError(originalMessage)) { return { type: 'version', enhancedMessage: this.enhanceVersionCompatibilityError(originalMessage) }; } // Default: return original message with basic enhancement return { type: 'unknown', enhancedMessage: `${originalMessage}\n\nTroubleshooting steps:\n- Run 'kubectl cluster-info' to verify cluster connectivity\n- Check your kubeconfig with 'kubectl config view'\n- Verify cluster endpoint accessibility` }; } private static isNetworkError(message: string): boolean { // Fixed: Avoid catastrophic backtracking by using non-overlapping alternation const networkPatterns = [ 'getaddrinfo ENOTFOUND', 'timeout', 'ECONNREFUSED', 'ENOTFOUND', 'network', 'unreachable' ]; return networkPatterns.some(pattern => message.toLowerCase().includes(pattern.toLowerCase())); } private static isAuthenticationError(message: string): boolean { // Fixed: Avoid catastrophic backtracking by using non-overlapping alternation const authPatterns = [ 'unauthorized', 'invalid bearer token', 'certificate', 'auth', 'authentication' ]; return authPatterns.some(pattern => message.toLowerCase().includes(pattern.toLowerCase())); } private static isAuthorizationError(message: string): boolean { return /forbidden|cannot list|cannot get|cannot create|RBAC|permission denied/i.test(message); } private static isAPIAvailabilityError(message: string): boolean { return /server could not find|resource type.*not found|doesn't have a resource type|no matches for kind/i.test(message); } private static isKubeconfigError(message: string): boolean { // Be more specific - don't match "path does not exist" errors which are about manifest files return /context.*does not exist|kubeconfig.*not found|invalid.*kubeconfig|config.*not found|no Auth Provider/i.test(message) && !/the path.*does not exist/.test(message); } private static isVersionCompatibilityError(message: string): boolean { return /server version|version.*old|unsupported.*version|api.*version/i.test(message); } private static enhanceNetworkError(message: string): string { if (message.includes('getaddrinfo ENOTFOUND')) { return `DNS resolution failed: Cannot resolve cluster endpoint hostname.\n\nTroubleshooting steps:\n- Check cluster endpoint in kubeconfig: kubectl config view\n- Verify network connectivity and DNS settings\n- Confirm cluster is running and accessible\n- Check VPN connection if using private cluster\n\nOriginal error: ${message}`; } if (message.includes('timeout')) { return `Connection timeout: Unable to reach cluster within timeout period.\n\nTroubleshooting steps:\n- Check network latency to cluster endpoint\n- Increase timeout value if needed\n- Verify cluster is responsive: kubectl get nodes\n- Check firewall and proxy settings\n\nOriginal error: ${message}`; } return `Network connectivity issue detected.\n\nTroubleshooting steps:\n- Verify cluster endpoint accessibility\n- Run 'kubectl cluster-info' to test connectivity\n- Check network and firewall settings\n- Confirm cluster is running\n\nOriginal error: ${message}`; } private static enhanceAuthenticationError(message: string): string { if (message.includes('invalid bearer token')) { return `Token may be expired: Bearer token authentication failed.\n\nTroubleshooting steps:\n- Token may be expired - refresh credentials\n- Check token format in kubeconfig\n- Re-authenticate with cluster: kubectl auth login\n- Verify service account token if applicable\n\nOriginal error: ${message}`; } if (message.includes('certificate')) { return `Certificate authentication failed: Client certificate validation error.\n\nTroubleshooting steps:\n- Verify certificate path in kubeconfig\n- Check certificate expiration date\n- Ensure certificate authority (CA) bundle is correct\n- Re-generate client certificates if needed\n\nOriginal error: ${message}`; } if (message.includes('no Auth Provider found')) { return `Authentication provider not available: Required auth plugin missing.\n\nTroubleshooting steps:\n- Install required authentication plugin (e.g., OIDC)\n- Check kubectl config for auth provider configuration\n- Verify authentication method compatibility\n- Consult cluster administrator for auth setup\n\nOriginal error: ${message}`; } return `Authentication failed: Invalid or missing credentials.\n\nTroubleshooting steps:\n- Verify credentials in kubeconfig\n- Re-authenticate with cluster\n- Check authentication method configuration\n- Contact cluster administrator if needed\n\nOriginal error: ${message}`; } private static enhanceAuthorizationError(message: string): string { if (message.includes('customresourcedefinitions')) { return `CRD discovery requires cluster-level permissions: Insufficient RBAC permissions.\n\nTroubleshooting steps:\n- CRD discovery requires admin privileges\n- Request cluster-admin role or CRD read permissions\n- Contact cluster administrator for permission escalation\n- Use 'kubectl auth can-i list customresourcedefinitions' to check permissions\n\nOriginal error: ${message}`; } if (message.includes('forbidden')) { return `Insufficient permissions: RBAC restrictions prevent this operation.\n\nTroubleshooting steps:\n- RBAC role required for resource access\n- Request appropriate permissions from cluster administrator\n- Check current permissions: kubectl auth can-i list <resource>\n- Consider using cluster-admin role for discovery operations\n\nOriginal error: ${message}`; } return `Permission denied: Insufficient RBAC permissions for cluster access.\n\nTroubleshooting steps:\n- Request appropriate RBAC permissions\n- Check current access: kubectl auth can-i list <resource>\n- Contact cluster administrator for role assignment\n- Verify service account permissions if applicable\n\nOriginal error: ${message}`; } private static enhanceAPIAvailabilityError(message: string): string { if (message.includes('apps/v1beta1')) { return `API version not supported: Cluster doesn't support requested API version.\n\nTroubleshooting steps:\n- Try different API version (e.g., apps/v1 instead of apps/v1beta1)\n- Check available API versions: kubectl api-versions\n- Verify Kubernetes cluster version compatibility\n- Consult API migration guides for version changes\n\nOriginal error: ${message}`; } return `API resource not available: Requested resource type not found in cluster.\n\nTroubleshooting steps:\n- Check available resources: kubectl api-resources\n- Verify cluster supports required resource types\n- Check Kubernetes version compatibility\n- Confirm cluster configuration and enabled APIs\n\nOriginal error: ${message}`; } private static enhanceKubeconfigError(message: string): string { if (message.includes('context') && message.includes('does not exist')) { return `Context not found: Specified context doesn't exist in kubeconfig.\n\nTroubleshooting steps:\n- List available contexts: kubectl config get-contexts\n- Set correct context: kubectl config use-context <context-name>\n- Verify kubeconfig file contains required context\n- Check context name spelling and case sensitivity\n\nOriginal error: ${message}`; } if (message.includes('not found')) { return `Kubeconfig file not found: Cannot locate configuration file.\n\nTroubleshooting steps:\n- Check file path exists and is accessible\n- Verify kubeconfig file permissions\n- Set KUBECONFIG environment variable if needed\n- Create kubeconfig file or copy from cluster administrator\n\nOriginal error: ${message}`; } return `Invalid kubeconfig format: Configuration file has syntax or format errors.\n\nTroubleshooting steps:\n- Validate YAML syntax in kubeconfig file\n- Check file structure: kubectl config view\n- Restore from backup or re-download from cluster\n- Verify all required sections (clusters, contexts, users)\n\nOriginal error: ${message}`; } private static enhanceVersionCompatibilityError(message: string): string { return `Kubernetes version compatibility issue: Version mismatch detected.\n\nTroubleshooting steps:\n- Check cluster and client versions: kubectl version\n- Verify supported Kubernetes versions for this tool\n- Update kubectl client if needed\n- Consult compatibility matrix for version support\n\nOriginal error: ${message}`; } }

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/vfarcic/dot-ai'

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