Skip to content

Commit 3b8cc30

Browse files
committed
feat: add cp command and test
1 parent 24aec77 commit 3b8cc30

File tree

8 files changed

+316
-2
lines changed

8 files changed

+316
-2
lines changed

examples/typescript/cp/cp-example.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as k8s from '@kubernetes/client-node';
2+
3+
const kc = new k8s.KubeConfig();
4+
kc.loadFromDefault();
5+
6+
const cp = new k8s.Cp(kc);
7+
cp.cpFromPod('default', 'nginx-4217019353-9gl4s', 'nginx', './test.txt', '/tmp');

examples/typescript/cp/test.txt

Whitespace-only changes.

package-lock.json

Lines changed: 125 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
"main": "dist/index.js",
1919
"types": "dist/index.d.ts",
2020
"scripts": {
21-
"format": "prettier --loglevel error --write './src/**/*.ts'",
22-
"lint": "tslint --project \".\" && prettier --check './src/**/*.ts' && tslint --project \"./examples/typescript\"",
21+
"format": "prettier --loglevel error --write \"./src/**/*.ts\"",
22+
"lint": "tslint --project \".\" && prettier --check \"./src/**/*.ts\" && tslint --project \"./examples/typescript\"",
2323
"clean": "rm -Rf node_modules/ dist/",
2424
"build": "tsc",
2525
"generate": "./generate-client.sh",
@@ -56,6 +56,7 @@
5656
"@types/js-yaml": "^3.12.1",
5757
"@types/node": "^10.12.0",
5858
"@types/request": "^2.47.1",
59+
"@types/tar": "^4.0.3",
5960
"@types/underscore": "^1.8.9",
6061
"@types/ws": "^6.0.1",
6162
"byline": "^5.0.0",
@@ -67,6 +68,8 @@
6768
"request": "^2.88.0",
6869
"rfc4648": "^1.3.0",
6970
"shelljs": "^0.8.2",
71+
"tar": "^6.0.2",
72+
"tmp-promise": "^3.0.2",
7073
"tslib": "^1.9.3",
7174
"underscore": "^1.9.1",
7275
"ws": "^6.1.0"

src/cp.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import * as fs from 'fs';
2+
import { WritableStreamBuffer } from 'stream-buffers';
3+
import * as tar from 'tar';
4+
import * as tmp from 'tmp-promise';
5+
6+
import { KubeConfig } from './config';
7+
import { Exec } from './exec';
8+
9+
export class Cp {
10+
public execInstance: Exec;
11+
public constructor(config: KubeConfig, execInstance?: Exec) {
12+
this.execInstance = execInstance || new Exec(config);
13+
}
14+
15+
/**
16+
* @param {string} namespace - The namespace of the pod to exec the command inside.
17+
* @param {string} podName - The name of the pod to exec the command inside.
18+
* @param {string} containerName - The name of the container in the pod to exec the command inside.
19+
* @param {string} srcPath - The source path in the pod
20+
* @param {string} tgtPath - The target path in local
21+
*/
22+
public async cpFromPod(
23+
namespace: string,
24+
podName: string,
25+
containerName: string,
26+
srcPath: string,
27+
tgtPath: string,
28+
): Promise<void> {
29+
const tmpFile = tmp.fileSync();
30+
const tmpFileName = tmpFile.name;
31+
const command = ['tar', 'cf', '-', srcPath];
32+
const writerStream = fs.createWriteStream(tmpFileName);
33+
const errStream = new WritableStreamBuffer();
34+
this.execInstance.exec(
35+
namespace,
36+
podName,
37+
containerName,
38+
command,
39+
writerStream,
40+
errStream,
41+
null,
42+
false,
43+
async () => {
44+
if (errStream.size()) {
45+
throw new Error(`Error from cpFromPod - details: \n ${errStream.getContentsAsString()}`);
46+
}
47+
await tar.x({
48+
file: tmpFileName,
49+
cwd: tgtPath,
50+
});
51+
},
52+
);
53+
}
54+
55+
/**
56+
* @param {string} namespace - The namespace of the pod to exec the command inside.
57+
* @param {string} podName - The name of the pod to exec the command inside.
58+
* @param {string} containerName - The name of the container in the pod to exec the command inside.
59+
* @param {string} srcPath - The source path in local
60+
* @param {string} tgtPath - The target path in the pod
61+
*/
62+
public async cpToPod(
63+
namespace: string,
64+
podName: string,
65+
containerName: string,
66+
srcPath: string,
67+
tgtPath: string,
68+
): Promise<void> {
69+
const tmpFile = tmp.fileSync();
70+
const tmpFileName = tmpFile.name;
71+
const command = ['tar', 'xf', '-', '-C', tgtPath];
72+
await tar.c(
73+
{
74+
file: tmpFile.name,
75+
},
76+
[srcPath],
77+
);
78+
const readStream = fs.createReadStream(tmpFileName);
79+
const errStream = new WritableStreamBuffer();
80+
this.execInstance.exec(
81+
namespace,
82+
podName,
83+
containerName,
84+
command,
85+
null,
86+
errStream,
87+
readStream,
88+
false,
89+
async () => {
90+
if (errStream.size()) {
91+
throw new Error(`Error from cpToPod - details: \n ${errStream.getContentsAsString()}`);
92+
}
93+
},
94+
);
95+
}
96+
}

src/cp_test.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { anything, anyFunction, instance, mock, verify, when } from 'ts-mockito';
2+
import * as querystring from 'querystring';
3+
import * as WebSocket from 'isomorphic-ws';
4+
5+
import { CallAwaiter } from '../test';
6+
import { KubeConfig } from './config';
7+
import { Exec } from './exec';
8+
import { Cp } from './cp';
9+
import { WebSocketHandler, WebSocketInterface } from './web-socket-handler';
10+
11+
describe('Cp', () => {
12+
describe('cpFromPod', () => {
13+
it('should run create tar command to a url', async () => {
14+
const kc = new KubeConfig();
15+
const fakeWebSocket: WebSocketInterface = mock(WebSocketHandler);
16+
const exec = new Exec(kc, instance(fakeWebSocket));
17+
const cp = new Cp(kc, exec);
18+
19+
const namespace = 'somenamespace';
20+
const pod = 'somepod';
21+
const container = 'container';
22+
const srcPath = '/';
23+
const tgtPath = '/';
24+
const cmdArray = ['tar', 'cf', '-', srcPath];
25+
const path = `/api/v1/namespaces/${namespace}/pods/${pod}/exec`;
26+
27+
const query = {
28+
stdout: true,
29+
stderr: true,
30+
stdin: false,
31+
tty: false,
32+
command: cmdArray,
33+
container,
34+
};
35+
const queryStr = querystring.stringify(query);
36+
37+
await cp.cpFromPod(namespace, pod, container, srcPath, tgtPath);
38+
// tslint:disable-next-line:max-line-length
39+
verify(fakeWebSocket.connect(`${path}?${queryStr}`, null, anyFunction())).called();
40+
});
41+
});
42+
43+
describe('cpToPod', () => {
44+
it('should run extract tar command to a url', async () => {
45+
const kc = new KubeConfig();
46+
const fakeWebSocketInterface: WebSocketInterface = mock(WebSocketHandler);
47+
const fakeWebSocket: WebSocket = mock(WebSocket);
48+
const callAwaiter: CallAwaiter = new CallAwaiter();
49+
const exec = new Exec(kc, instance(fakeWebSocketInterface));
50+
const cp = new Cp(kc, exec);
51+
52+
const namespace = 'somenamespace';
53+
const pod = 'somepod';
54+
const container = 'container';
55+
const srcPath = 'testdata/archive.txt';
56+
const tgtPath = '/';
57+
const cmdArray = ['tar', 'xf', '-', '-C', tgtPath];
58+
const path = `/api/v1/namespaces/${namespace}/pods/${pod}/exec`;
59+
60+
const query = {
61+
stdout: false,
62+
stderr: true,
63+
stdin: true,
64+
tty: false,
65+
command: cmdArray,
66+
container,
67+
};
68+
const queryStr = querystring.stringify(query);
69+
70+
const fakeConn: WebSocket = instance(fakeWebSocket);
71+
when(fakeWebSocketInterface.connect(`${path}?${queryStr}`, null, anyFunction())).thenResolve(
72+
fakeConn,
73+
);
74+
when(fakeWebSocket.send(anything())).thenCall(callAwaiter.resolveCall('send'));
75+
when(fakeWebSocket.close()).thenCall(callAwaiter.resolveCall('close'));
76+
77+
await cp.cpToPod(namespace, pod, container, srcPath, tgtPath);
78+
verify(fakeWebSocketInterface.connect(`${path}?${queryStr}`, null, anyFunction())).called();
79+
});
80+
});
81+
});

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ export * from './log';
1111
export * from './informer';
1212
export * from './top';
1313
export * from './object';
14+
export * from './cp';

testdata/archive.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test

0 commit comments

Comments
 (0)