/** * Service config set command */ import { eq } from 'drizzle-orm'; import { z } from 'zod'; import { getDb } from '../../db/client'; import { type NetworkZone, containerServices } from '../../db/schema'; import { getContainerServiceByServiceId } from '../../services/container-service'; import { getArg, validateRequiredArgs } from '../parser'; import type { CommandResult } from '../types'; /** * Handle service config set command * * Usage: celilo service config set * * @param args - Command arguments * @returns Command result */ export async function handleServiceConfigSet(args: string[]): Promise { const error = validateRequiredArgs(args, 3); if (error) { return { success: false, error: `${error}\n\nUsage: celilo service config set `, }; } const serviceId = getArg(args, 0); const key = getArg(args, 1); const valueRaw = getArg(args, 2); if (!serviceId || !key || !valueRaw) { return { success: false, error: 'Service ID, key, and value are required', }; } const service = await getContainerServiceByServiceId(serviceId); if (!service) { return { success: false, error: `Service not found: ${serviceId}`, }; } // Validate key const validKeys = ['name', 'zones', 'providerConfig']; if (!validKeys.includes(key)) { return { success: false, error: `Invalid config key '${key}'.\n\nValid keys: ${validKeys.join(', ')}`, }; } const db = getDb(); const now = new Date(); try { // Handle different key types if (key === 'name') { // Simple string value await db .update(containerServices) .set({ name: valueRaw, updatedAt: now, }) .where(eq(containerServices.id, service.id)); return { success: true, message: `Updated service ${serviceId}: ${key} = ${valueRaw}`, }; } if (key === 'zones') { // Parse as JSON array of NetworkZone const ZonesSchema = z.array( z.enum(['internal', 'dmz', 'app', 'secure', 'secure-mgmt', 'external']), ); const parsed = JSON.parse(valueRaw); const zones = ZonesSchema.parse(parsed) as NetworkZone[]; await db .update(containerServices) .set({ zones, // Drizzle auto-stringifies with mode: 'json' updatedAt: now, }) .where(eq(containerServices.id, service.id)); return { success: true, message: `Updated service ${serviceId}: ${key} = ${JSON.stringify(zones)}`, }; } if (key === 'providerConfig') { // Parse as JSON object const parsed = JSON.parse(valueRaw); if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) { return { success: false, error: 'providerConfig must be a JSON object', }; } await db .update(containerServices) .set({ providerConfig: parsed, // Drizzle auto-stringifies with mode: 'json' updatedAt: now, }) .where(eq(containerServices.id, service.id)); return { success: true, message: `Updated service ${serviceId}: ${key} = ${JSON.stringify(parsed)}`, }; } return { success: false, error: `Config key '${key}' is not implemented`, }; } catch (error) { if (error instanceof SyntaxError) { return { success: false, error: `Invalid JSON value: ${error.message}`, }; } if (error instanceof z.ZodError) { return { success: false, error: `Validation failed: ${error.errors.map((e) => e.message).join(', ')}`, }; } return { success: false, error: `Failed to set config: ${error instanceof Error ? error.message : String(error)}`, }; } }