6import { spawn } from 'child_process' 9const doKubeCmd = async (...restCmd: string[]) => { 11 const cmdA = [cluster_name, ...restCmd] 12 console.log(cmdA.join(' ')) 16type KubeCpDownProps = { podName: string, containerName?: string, fromRemotePath: string, toLocalPath: string } 17type KubeCpUpProps = { podName: string, containerName?: string, toRemotePath: string, fromLocalPath: string } 19export const kubeCpDown = async ({podName, fromRemotePath, toLocalPath}: KubeCpDownProps) => { 21 'cp', '--retries=-1', `${podName}:${fromRemotePath}`, 26export const kubeCpUp = async ({podName, containerName, toRemotePath, fromLocalPath}: KubeCpUpProps) => { 28 'cp', ...(containerName ? ['-c', containerName] : []), fromLocalPath, 29 `${podName}:${toRemotePath}`, 33type KubeExecCatProps = { podName: string, containerName?: string, fromRemotePath: string, toLocalPath: string, expectedSize?: number } 35const doKubeExecCatRange = async ({podName, containerName, fromRemotePath, toLocalPath, skipBytes}: KubeExecCatProps & {skipBytes: number}) => { 39 const { kubeTlsInsecure = false } = getCurKlusterCfg(cluster_name) as { kubeTlsInsecure?: boolean } 40 const podCmd = skipBytes > 0 41 ? ['tail', '-c', `+${skipBytes + 1}`, fromRemotePath] 42 : ['cat', fromRemotePath] 45 kubeTlsInsecure && '--insecure-skip-tls-verify', 46 'exec', '-i', podName, 47 ...(containerName ? ['-c', containerName] : []), 49 ].filter(Boolean) as string[] 50 console.log(cmdA.join(' ')) 52 return await new Promise<{code: number | null, stderr: string}>((resolv) => { 53 const flags = skipBytes > 0 ? 'a' : 'w' 54 const proc = spawn(cmdA[0], cmdA.slice(1), { 55 env: { ...process.env, KUBECONFIG: resolvedPath }, 56 stdio: ['ignore', fs.openSync(toLocalPath, flags), 'pipe'], 59 if (proc.stderr) proc.stderr.on('data', (chunk: Buffer) => { stderr += chunk.toString() }) 60 proc.on('close', (code) => { 61 resolv({code, stderr}) 63 proc.on('error', (err) => { 64 resolv({code: -1, stderr: err.message}) 69export const kubeExecCat = async (props: KubeExecCatProps) => { 71 for (let attempt = 1; attempt <= maxAttempts; attempt++) { 72 const localSize = fs.existsSync(props.toLocalPath) ? fs.statSync(props.toLocalPath).size : 0 73 if (props.expectedSize && localSize === props.expectedSize) { 74 console.log(`kubeExecCat: size match ${localSize}`) 77 const {code, stderr} = await doKubeExecCatRange({...props, skipBytes: localSize}) 78 const newLocalSize = fs.statSync(props.toLocalPath).size 79 if (code === 0 && (!props.expectedSize || newLocalSize === props.expectedSize)) { 82 console.log(`kubeExecCat attempt ${attempt}/${maxAttempts} code=${code} localSize=${newLocalSize} expectedSize=${props.expectedSize}`) 83 if (attempt < maxAttempts) await sleep(3000) 85 throw new Error(`!kubeExecCat ${maxAttempts} attempts`)