diff --git a/src/cp.ts b/src/cp.ts index 7e676bfb0b..f8920e908d 100644 --- a/src/cp.ts +++ b/src/cp.ts @@ -26,7 +26,7 @@ export class Cp { tgtPath: string, cwd?: string, ): Promise { - const command = ['tar', 'zcf', '-']; + const command = ['tar', 'cf', '-']; if (cwd) { command.push('-C', cwd); } diff --git a/src/cp_test.ts b/src/cp_test.ts index 0782106cba..fb38247df3 100644 --- a/src/cp_test.ts +++ b/src/cp_test.ts @@ -22,7 +22,7 @@ describe('Cp', () => { const container = 'container'; const srcPath = '/'; const tgtPath = '/'; - const cmdArray = ['tar', 'zcf', '-', srcPath]; + const cmdArray = ['tar', 'cf', '-', srcPath]; const path = `/api/v1/namespaces/${namespace}/pods/${pod}/exec`; const query = { @@ -51,7 +51,7 @@ describe('Cp', () => { const srcPath = '/'; const tgtPath = '/'; const cwd = '/abc'; - const cmdArray = ['tar', 'zcf', '-', '-C', cwd, srcPath]; + const cmdArray = ['tar', 'cf', '-', '-C', cwd, srcPath]; const path = `/api/v1/namespaces/${namespace}/pods/${pod}/exec`; const query = { diff --git a/src/test/integration/cpFromPod.ts b/src/test/integration/cpFromPod.ts new file mode 100644 index 0000000000..001368dfdf --- /dev/null +++ b/src/test/integration/cpFromPod.ts @@ -0,0 +1,79 @@ +import assert from 'node:assert'; +import fs from 'node:fs'; +import path from 'node:path'; +import os from 'node:os'; +import { setTimeout } from 'node:timers/promises'; +import { CoreV1Api, KubeConfig, V1Pod } from '../../index.js'; +import { Cp } from '../../cp.js'; +import { generateName } from './name.js'; + +export default async function cpFromPod() { + const kc = new KubeConfig(); + kc.loadFromDefault(); + + const coreV1Client = kc.makeApiClient(CoreV1Api); + const cp = new Cp(kc); + + const testPodName = generateName('cp-test-pod'); + const namespace = 'default'; + + const pod = new V1Pod(); + pod.metadata = { name: testPodName }; + pod.spec = { + containers: [ + { + name: 'test-container', + image: 'busybox', + command: ['sh', '-c', 'echo "test content" > /tmp/test.txt && sleep 3600'], + }, + ], + restartPolicy: 'Never', + }; + + console.log(`Creating pod ${testPodName}`); + await coreV1Client.createNamespacedPod({ namespace, body: pod }); + + console.log('Waiting for pod to be ready...'); + let podReady = false; + for (let i = 0; i < 30; i++) { + const currentPod = await coreV1Client.readNamespacedPod({ name: testPodName, namespace }); + if (currentPod.status?.phase === 'Running') { + podReady = true; + break; + } + await setTimeout(1000); + } + + assert.strictEqual(podReady, true, 'Pod did not become ready in time'); + console.log('Pod is ready'); + + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'k8s-cp-test-')); + + try { + console.log('Copying file from pod...'); + + cp.cpFromPod(namespace, testPodName, 'test-container', 'test.txt', tempDir, '/tmp'); + + // Wait for file to appear + const copiedFilePath = path.join(tempDir, 'test.txt'); + let fileExists = false; + for (let i = 0; i < 20; i++) { + if (fs.existsSync(copiedFilePath)) { + fileExists = true; + break; + } + await setTimeout(500); + } + + assert.strictEqual(fileExists, true, 'File was not copied'); + + const content = fs.readFileSync(copiedFilePath, 'utf-8'); + assert.strictEqual(content.trim(), 'test content', 'File content does not match'); + + console.log('cpFromPod test passed!'); + } finally { + console.log('Cleaning up...'); + await coreV1Client.deleteNamespacedPod({ name: testPodName, namespace }); + fs.rmSync(tempDir, { recursive: true, force: true }); + } +} diff --git a/src/test/integration/index.ts b/src/test/integration/index.ts index 5065dcd429..ee26fa03df 100644 --- a/src/test/integration/index.ts +++ b/src/test/integration/index.ts @@ -1,5 +1,7 @@ import patchNamespace from './patchNamespace.js'; +import cpFromPod from './cpFromPod.js'; console.log('Integration testing'); await patchNamespace(); +await cpFromPod();