sdk: fix piping stdio of Daemons, support onStdOut/onStderr (#2762)

This commit is contained in:
Remco Ros
2024-10-25 00:29:12 +02:00
committed by GitHub
parent 7694b68e06
commit 42cfd69463
5 changed files with 26 additions and 15 deletions

View File

@@ -151,7 +151,7 @@ export class DockerProcedureContainer {
}
}
async spawn(commands: string[]): Promise<cp.ChildProcessWithoutNullStreams> {
async spawn(commands: string[]): Promise<cp.ChildProcess> {
return await this.subcontainer.spawn(commands)
}
}

View File

@@ -17,7 +17,7 @@ export class CommandController {
readonly runningAnswer: Promise<unknown>,
private state: { exited: boolean },
private readonly subcontainer: SubContainer,
private process: cp.ChildProcessWithoutNullStreams,
private process: cp.ChildProcess,
readonly sigtermTimeout: number = DEFAULT_SIGTERM_TIMEOUT,
) {}
static of<Manifest extends T.SDKManifest>() {
@@ -43,8 +43,8 @@ export class CommandController {
| undefined
cwd?: string | undefined
user?: string | undefined
onStdout?: (x: Buffer) => null
onStderr?: (x: Buffer) => null
onStdout?: (chunk: Buffer | string | any) => void
onStderr?: (chunk: Buffer | string | any) => void
},
) => {
const commands = splitCommand(command)
@@ -62,7 +62,7 @@ export class CommandController {
}
return subc
})()
let childProcess: cp.ChildProcessWithoutNullStreams
let childProcess: cp.ChildProcess
if (options.runAsInit) {
childProcess = await subc.launch(commands, {
env: options.env,
@@ -70,8 +70,13 @@ export class CommandController {
} else {
childProcess = await subc.spawn(commands, {
env: options.env,
stdio: options.onStdout || options.onStderr ? "pipe" : "inherit",
})
}
if (options.onStdout) childProcess.stdout?.on("data", options.onStdout)
if (options.onStderr) childProcess.stderr?.on("data", options.onStderr)
const state = { exited: false }
const answer = new Promise<null>((resolve, reject) => {
childProcess.on("exit", (code) => {

View File

@@ -37,8 +37,8 @@ export class Daemon {
| undefined
cwd?: string | undefined
user?: string | undefined
onStdout?: (x: Buffer) => null
onStderr?: (x: Buffer) => null
onStdout?: (chunk: Buffer | string | any) => void
onStderr?: (chunk: Buffer | string | any) => void
sigtermTimeout?: number
},
) => {

View File

@@ -39,6 +39,8 @@ type DaemonsParams<
ready: Ready
requires: Exclude<Ids, Id>[]
sigtermTimeout?: number
onStdout?: (chunk: Buffer | string | any) => void
onStderr?: (chunk: Buffer | string | any) => void
}
type ErrorDuplicateId<Id extends string> = `The id '${Id}' is already used`

View File

@@ -35,8 +35,8 @@ export interface ExecSpawnable {
): Promise<ExecResults>
spawn(
command: string[],
options?: CommandOptions,
): Promise<cp.ChildProcessWithoutNullStreams>
options?: CommandOptions & StdioOptions,
): Promise<cp.ChildProcess>
}
/**
* Want to limit what we can do in a container, so we want to launch a container with a specific image and the mounts.
@@ -332,8 +332,8 @@ export class SubContainer implements ExecSpawnable {
async spawn(
command: string[],
options?: CommandOptions,
): Promise<cp.ChildProcessWithoutNullStreams> {
options: CommandOptions & StdioOptions = { stdio: "inherit" },
): Promise<cp.ChildProcess> {
await this.waitProc()
const imageMeta: any = await fs
.readFile(`/media/startos/images/${this.imageId}.json`, {
@@ -342,12 +342,12 @@ export class SubContainer implements ExecSpawnable {
.catch(() => "{}")
.then(JSON.parse)
let extra: string[] = []
if (options?.user) {
if (options.user) {
extra.push(`--user=${options.user}`)
delete options.user
}
let workdir = imageMeta.workdir || "/"
if (options?.cwd) {
if (options.cwd) {
workdir = options.cwd
delete options.cwd
}
@@ -387,8 +387,8 @@ export class SubContainerHandle implements ExecSpawnable {
}
spawn(
command: string[],
options?: CommandOptions,
): Promise<cp.ChildProcessWithoutNullStreams> {
options: CommandOptions & StdioOptions = { stdio: "inherit" },
): Promise<cp.ChildProcess> {
return this.subContainer.spawn(command, options)
}
}
@@ -399,6 +399,10 @@ export type CommandOptions = {
user?: string
}
export type StdioOptions = {
stdio?: cp.IOType
}
export type MountOptions =
| MountOptionsVolume
| MountOptionsAssets