0
# Pod Operations
1
2
High-level classes for interactive pod operations including command execution, container attachment, port forwarding, and file transfer. These classes provide convenient abstractions over WebSocket-based Kubernetes APIs.
3
4
## Capabilities
5
6
### Exec Class
7
8
Execute commands in pod containers with support for interactive sessions, TTY mode, and stream handling.
9
10
```typescript { .api }
11
/**
12
* Execute commands in pod containers
13
*/
14
class Exec {
15
constructor(config: KubeConfig, wsInterface?: WebSocketInterface);
16
17
/**
18
* Execute a command in a container
19
* @param namespace - Pod namespace
20
* @param podName - Pod name
21
* @param containerName - Container name
22
* @param command - Command to execute (string or array)
23
* @param stdout - Output stream for stdout
24
* @param stderr - Output stream for stderr
25
* @param stdin - Input stream for stdin
26
* @param tty - Enable TTY mode
27
* @param statusCallback - Callback for command status
28
* @returns Promise that resolves to WebSocket connection
29
*/
30
exec(
31
namespace: string,
32
podName: string,
33
containerName: string,
34
command: string | string[],
35
stdout: stream.Writable | null,
36
stderr: stream.Writable | null,
37
stdin: stream.Readable | null,
38
tty: boolean,
39
statusCallback?: (status: V1Status) => void
40
): Promise<WebSocket.WebSocket>;
41
}
42
```
43
44
**Usage Examples:**
45
46
```typescript
47
import { KubeConfig, Exec } from '@kubernetes/client-node';
48
import * as stream from 'stream';
49
50
const kc = new KubeConfig();
51
kc.loadFromDefault();
52
53
const exec = new Exec(kc);
54
55
// Execute a simple command
56
const stdout = new stream.PassThrough();
57
const stderr = new stream.PassThrough();
58
59
stdout.on('data', (data) => {
60
console.log('STDOUT:', data.toString());
61
});
62
63
stderr.on('data', (data) => {
64
console.error('STDERR:', data.toString());
65
});
66
67
try {
68
const ws = await exec.exec(
69
'default', // namespace
70
'my-pod', // pod name
71
'my-container', // container name
72
['ls', '-la', '/'], // command
73
stdout, // stdout stream
74
stderr, // stderr stream
75
null, // stdin stream
76
false, // tty mode
77
(status) => { // status callback
78
console.log('Command status:', status);
79
}
80
);
81
82
// Handle WebSocket events
83
ws.on('close', (code, reason) => {
84
console.log('Connection closed:', code, reason);
85
});
86
} catch (error) {
87
console.error('Exec error:', error);
88
}
89
90
// Interactive shell session with TTY
91
const process = require('process');
92
93
const interactiveExec = async () => {
94
try {
95
const ws = await exec.exec(
96
'default',
97
'my-pod',
98
'my-container',
99
['/bin/bash'], // shell command
100
process.stdout, // stdout to console
101
process.stderr, // stderr to console
102
process.stdin, // stdin from console
103
true // TTY mode for interactive session
104
);
105
106
// Handle process signals
107
process.on('SIGINT', () => {
108
ws.close();
109
});
110
} catch (error) {
111
console.error('Interactive exec error:', error);
112
}
113
};
114
```
115
116
### Attach Class
117
118
Attach to running containers to interact with their primary process.
119
120
```typescript { .api }
121
/**
122
* Attach to running containers
123
*/
124
class Attach {
125
constructor(config: KubeConfig, websocketInterface?: WebSocketInterface);
126
127
/**
128
* Attach to a running container
129
* @param namespace - Pod namespace
130
* @param podName - Pod name
131
* @param containerName - Container name
132
* @param stdout - Output stream for stdout
133
* @param stderr - Output stream for stderr
134
* @param stdin - Input stream for stdin
135
* @param tty - Enable TTY mode
136
* @returns Promise that resolves to WebSocket connection
137
*/
138
attach(
139
namespace: string,
140
podName: string,
141
containerName: string,
142
stdout: stream.Writable | any,
143
stderr: stream.Writable | any,
144
stdin: stream.Readable | any,
145
tty: boolean
146
): Promise<WebSocket.WebSocket>;
147
}
148
```
149
150
**Usage Examples:**
151
152
```typescript
153
import { KubeConfig, Attach } from '@kubernetes/client-node';
154
155
const kc = new KubeConfig();
156
kc.loadFromDefault();
157
158
const attach = new Attach(kc);
159
160
// Attach to container's main process
161
try {
162
const ws = await attach.attach(
163
'default',
164
'my-pod',
165
'my-container',
166
process.stdout, // stdout
167
process.stderr, // stderr
168
process.stdin, // stdin
169
true // TTY mode
170
);
171
172
console.log('Attached to container');
173
174
ws.on('close', () => {
175
console.log('Detached from container');
176
});
177
} catch (error) {
178
console.error('Attach error:', error);
179
}
180
```
181
182
### PortForward Class
183
184
Forward local ports to pod ports for accessing services running inside containers.
185
186
```typescript { .api }
187
/**
188
* Forward local ports to pod ports
189
*/
190
class PortForward {
191
constructor(config: KubeConfig, disconnectOnErr?: boolean, handler?: WebSocketInterface);
192
193
/**
194
* Forward ports to a pod
195
* @param namespace - Pod namespace
196
* @param podName - Pod name
197
* @param targetPorts - Array of port numbers to forward
198
* @param output - Output stream for data
199
* @param err - Error stream
200
* @param input - Input stream for data
201
* @param retryCount - Number of retry attempts
202
* @returns Promise that resolves to WebSocket or connection function
203
*/
204
portForward(
205
namespace: string,
206
podName: string,
207
targetPorts: number[],
208
output: stream.Writable,
209
err: stream.Writable | null,
210
input: stream.Readable,
211
retryCount?: number
212
): Promise<WebSocket.WebSocket | (() => WebSocket.WebSocket | null)>;
213
}
214
```
215
216
**Usage Examples:**
217
218
```typescript
219
import { KubeConfig, PortForward } from '@kubernetes/client-node';
220
import * as net from 'net';
221
222
const kc = new KubeConfig();
223
kc.loadFromDefault();
224
225
const portForward = new PortForward(kc);
226
227
// Forward local port 8080 to pod port 80
228
const forwardPort = async () => {
229
const server = net.createServer((socket) => {
230
portForward.portForward(
231
'default', // namespace
232
'my-pod', // pod name
233
[80], // target ports
234
socket, // output stream
235
null, // error stream
236
socket, // input stream
237
0 // retry count
238
).then((ws) => {
239
console.log('Port forward established');
240
241
socket.on('close', () => {
242
if (typeof ws === 'function') {
243
const connection = ws();
244
if (connection) {
245
connection.close();
246
}
247
} else {
248
ws.close();
249
}
250
});
251
}).catch((error) => {
252
console.error('Port forward error:', error);
253
socket.destroy();
254
});
255
});
256
257
server.listen(8080, () => {
258
console.log('Local server listening on port 8080');
259
console.log('Forwarding to pod my-pod:80');
260
});
261
};
262
263
forwardPort();
264
265
// Simple port forwarding with streams
266
const simplePortForward = async () => {
267
const output = new stream.PassThrough();
268
const input = new stream.PassThrough();
269
270
try {
271
const ws = await portForward.portForward(
272
'default',
273
'my-pod',
274
[3000, 8080], // Forward multiple ports
275
output,
276
process.stderr,
277
input
278
);
279
280
console.log('Port forwarding active');
281
282
// Handle data
283
output.on('data', (data) => {
284
console.log('Received data:', data.toString());
285
});
286
287
} catch (error) {
288
console.error('Port forward failed:', error);
289
}
290
};
291
```
292
293
### Cp Class
294
295
Copy files to and from pod containers using tar-based transfer.
296
297
```typescript { .api }
298
/**
299
* Copy files to/from pod containers
300
*/
301
class Cp {
302
constructor(config: KubeConfig, execInstance?: Exec);
303
304
/**
305
* Copy file from pod to local filesystem
306
* @param namespace - Pod namespace
307
* @param podName - Pod name
308
* @param containerName - Container name
309
* @param srcPath - Source path in container
310
* @param tgtPath - Target path on local filesystem
311
* @returns Promise that resolves when copy is complete
312
*/
313
cpFromPod(
314
namespace: string,
315
podName: string,
316
containerName: string,
317
srcPath: string,
318
tgtPath: string
319
): Promise<void>;
320
321
/**
322
* Copy file from local filesystem to pod
323
* @param namespace - Pod namespace
324
* @param podName - Pod name
325
* @param containerName - Container name
326
* @param srcPath - Source path on local filesystem
327
* @param tgtPath - Target path in container
328
* @returns Promise that resolves when copy is complete
329
*/
330
cpToPod(
331
namespace: string,
332
podName: string,
333
containerName: string,
334
srcPath: string,
335
tgtPath: string
336
): Promise<void>;
337
}
338
```
339
340
**Usage Examples:**
341
342
```typescript
343
import { KubeConfig, Cp } from '@kubernetes/client-node';
344
345
const kc = new KubeConfig();
346
kc.loadFromDefault();
347
348
const cp = new Cp(kc);
349
350
// Copy file from pod to local system
351
const copyFromPod = async () => {
352
try {
353
await cp.cpFromPod(
354
'default', // namespace
355
'my-pod', // pod name
356
'my-container', // container name
357
'/app/config.json', // source path in pod
358
'./local-config.json' // target path locally
359
);
360
361
console.log('File copied from pod successfully');
362
} catch (error) {
363
console.error('Copy from pod failed:', error);
364
}
365
};
366
367
// Copy file from local system to pod
368
const copyToPod = async () => {
369
try {
370
await cp.cpToPod(
371
'default', // namespace
372
'my-pod', // pod name
373
'my-container', // container name
374
'./local-data.txt', // source path locally
375
'/tmp/data.txt' // target path in pod
376
);
377
378
console.log('File copied to pod successfully');
379
} catch (error) {
380
console.error('Copy to pod failed:', error);
381
}
382
};
383
384
// Copy directory from pod
385
const copyDirectoryFromPod = async () => {
386
try {
387
await cp.cpFromPod(
388
'default',
389
'my-pod',
390
'my-container',
391
'/app/logs/', // source directory in pod
392
'./pod-logs/' // target directory locally
393
);
394
395
console.log('Directory copied from pod successfully');
396
} catch (error) {
397
console.error('Directory copy failed:', error);
398
}
399
};
400
401
// Batch file operations
402
const batchOperations = async () => {
403
const operations = [
404
// Backup configuration
405
() => cp.cpFromPod('default', 'my-pod', 'app', '/etc/app/config.yaml', './backups/config.yaml'),
406
407
// Update configuration
408
() => cp.cpToPod('default', 'my-pod', 'app', './new-config.yaml', '/etc/app/config.yaml'),
409
410
// Copy logs
411
() => cp.cpFromPod('default', 'my-pod', 'app', '/var/log/app.log', './logs/app.log')
412
];
413
414
for (const operation of operations) {
415
try {
416
await operation();
417
} catch (error) {
418
console.error('Operation failed:', error);
419
}
420
}
421
};
422
```
423
424
### WebSocket Interface
425
426
All pod operations use WebSocket connections for real-time communication.
427
428
```typescript { .api }
429
/**
430
* WebSocket interface for customizing WebSocket behavior
431
*/
432
interface WebSocketInterface {
433
connect(
434
path: string,
435
textHandler: (text: string) => void,
436
binaryHandler: (binary: Buffer) => void
437
): WebSocket.WebSocket;
438
}
439
440
/**
441
* Default WebSocket handler
442
*/
443
class WebSocketHandler implements WebSocketInterface {
444
connect(
445
path: string,
446
textHandler: (text: string) => void,
447
binaryHandler: (binary: Buffer) => void
448
): WebSocket.WebSocket;
449
}
450
```
451
452
### Error Handling
453
454
Pod operations can fail for various reasons. Always handle errors appropriately:
455
456
```typescript
457
import { ApiException } from '@kubernetes/client-node';
458
459
const handlePodOperation = async () => {
460
try {
461
const ws = await exec.exec(
462
'default',
463
'my-pod',
464
'my-container',
465
['echo', 'hello'],
466
stdout,
467
stderr,
468
null,
469
false
470
);
471
} catch (error) {
472
if (error instanceof ApiException) {
473
console.error('API Error:', error.code);
474
if (error.code === 404) {
475
console.error('Pod not found');
476
} else if (error.code === 403) {
477
console.error('Access denied');
478
}
479
} else {
480
console.error('Network or other error:', error.message);
481
}
482
}
483
};
484
```
485
486
### Advanced Usage
487
488
**Custom WebSocket handling:**
489
490
```typescript
491
import { Exec, WebSocketInterface } from '@kubernetes/client-node';
492
493
class CustomWebSocketHandler implements WebSocketInterface {
494
connect(path: string, textHandler: (text: string) => void, binaryHandler: (binary: Buffer) => void) {
495
// Custom WebSocket implementation
496
const ws = new WebSocket(path);
497
498
ws.on('message', (data) => {
499
if (typeof data === 'string') {
500
textHandler(data);
501
} else {
502
binaryHandler(data as Buffer);
503
}
504
});
505
506
return ws;
507
}
508
}
509
510
const exec = new Exec(kc, new CustomWebSocketHandler());
511
```
512
513
**Stream processing with transforms:**
514
515
```typescript
516
import { Transform } from 'stream';
517
518
const colorOutput = new Transform({
519
transform(chunk, encoding, callback) {
520
// Add color codes to output
521
const colored = `\x1b[32m${chunk.toString()}\x1b[0m`;
522
callback(null, colored);
523
}
524
});
525
526
const ws = await exec.exec(
527
'default',
528
'my-pod',
529
'my-container',
530
['tail', '-f', '/var/log/app.log'],
531
colorOutput.pipe(process.stdout),
532
process.stderr,
533
null,
534
false
535
);
536
```