forked from snxraven/peardock
Ship remaining roadmap items: encrypted registry vault, peer invite/revoke, Swarm/plugins behind flags, binary streams, engine create validation, deploy rollback, schema validation, fleet/access UI, metrics, fuzz/load/soak tests, systemd packaging, and release tooling. Mark ROADMAP fully complete.
74 lines
2.5 KiB
JavaScript
74 lines
2.5 KiB
JavaScript
/**
|
|
* Docker Compose stack RPC handlers.
|
|
*/
|
|
import * as composeManager from '../utils/composeManager.js'
|
|
import * as validation from '../utils/validation.js'
|
|
import { docker } from '../services/docker.js'
|
|
import { broadcastContainers } from './containers.js'
|
|
|
|
export function registerStackHandlers(session) {
|
|
session.respond('deployStack', async (args) => {
|
|
const { composeContent, stackName } = args
|
|
if (!composeContent || !stackName) {
|
|
throw new Error('Compose content and stack name required')
|
|
}
|
|
const sanitizedStackName = validation.sanitizeString(stackName, 63)
|
|
if (!validation.isValidContainerName(sanitizedStackName)) {
|
|
throw new Error('Invalid stack name')
|
|
}
|
|
// Validate YAML early for clear errors
|
|
composeManager.validateComposeFile(composeContent)
|
|
const profiles = Array.isArray(args.profiles)
|
|
? args.profiles.map(String)
|
|
: typeof args.profiles === 'string'
|
|
? args.profiles.split(',').map((s) => s.trim()).filter(Boolean)
|
|
: []
|
|
const result = await composeManager.deployComposeStack(
|
|
docker,
|
|
composeContent,
|
|
sanitizedStackName,
|
|
{
|
|
overrideContent: args.overrideContent || args.override || null,
|
|
envFileContent: args.envFileContent || args.envFile || null,
|
|
profiles,
|
|
env: args.env && typeof args.env === 'object' ? args.env : {},
|
|
build: Boolean(args.build),
|
|
// Default true: tear down containers created in a failed partial deploy
|
|
rollback: args.rollback !== false,
|
|
}
|
|
)
|
|
await broadcastContainers()
|
|
return { success: true, ...result }
|
|
})
|
|
|
|
session.respond('listStacks', async () => {
|
|
const stacks = await composeManager.listStacks(docker)
|
|
return { type: 'stacks', data: stacks }
|
|
})
|
|
|
|
session.respond('removeStack', async (args) => {
|
|
const result = await composeManager.removeComposeStack(docker, args.stackName)
|
|
await broadcastContainers()
|
|
return { success: true, ...result }
|
|
})
|
|
|
|
session.respond('stackPs', async (args) => {
|
|
if (!args.stackName) throw new Error('stackName required')
|
|
return composeManager.stackPs(docker, args.stackName)
|
|
})
|
|
|
|
session.respond('stackLogs', async (args) => {
|
|
if (!args.stackName) throw new Error('stackName required')
|
|
return composeManager.stackLogs(docker, args.stackName, {
|
|
tail: args.tail,
|
|
})
|
|
})
|
|
|
|
session.respond('stackPull', async (args) => {
|
|
if (!args.stackName) throw new Error('stackName required')
|
|
return composeManager.stackPull(docker, args.stackName, {
|
|
composeContent: args.composeContent,
|
|
})
|
|
})
|
|
}
|