0
# Object Management and Utilities
1
2
Generic object management, YAML processing, health checking, patch strategies, and utility functions for working with Kubernetes resources and cluster operations.
3
4
## Capabilities
5
6
### KubernetesObjectApi
7
8
Generic API for working with any Kubernetes object type without needing specific API client classes.
9
10
```typescript { .api }
11
/**
12
* Generic API for any Kubernetes object type
13
*/
14
class KubernetesObjectApi {
15
/**
16
* Create instance from KubeConfig
17
*/
18
static makeApiClient(kc: KubeConfig): KubernetesObjectApi;
19
20
/**
21
* Create a Kubernetes object
22
* @param spec - Kubernetes object specification to create
23
* @param pretty - Pretty-print the output
24
* @param dryRun - Dry run mode ('All' or 'Server')
25
* @param fieldManager - Field manager name for server-side apply
26
* @param options - Optional configuration options
27
* @returns Promise that resolves to created object
28
*/
29
create<T extends KubernetesObject>(
30
spec: T,
31
pretty?: string,
32
dryRun?: string,
33
fieldManager?: string,
34
options?: Configuration
35
): Promise<T>;
36
37
/**
38
* Delete a Kubernetes object
39
* @param spec - Kubernetes object to delete
40
* @param pretty - Pretty-print the output
41
* @param dryRun - Dry run mode
42
* @param gracePeriodSeconds - Grace period for deletion
43
* @param orphanDependents - Whether to orphan dependents
44
* @param propagationPolicy - Propagation policy for deletion
45
* @param options - Optional configuration options
46
* @returns Promise that resolves to deletion status
47
*/
48
delete(
49
spec: KubernetesObject,
50
pretty?: string,
51
dryRun?: string,
52
gracePeriodSeconds?: number,
53
orphanDependents?: boolean,
54
propagationPolicy?: string,
55
options?: Configuration
56
): Promise<V1Status>;
57
58
/**
59
* Read a Kubernetes object
60
* @param spec - Kubernetes object header (only metadata.name and metadata.namespace used)
61
* @param pretty - Pretty-print the output
62
* @param exact - Should the export be exact
63
* @param exportt - Should this request return an export
64
* @param options - Optional configuration options
65
* @returns Promise that resolves to object
66
*/
67
read<T extends KubernetesObject>(
68
spec: KubernetesObjectHeader<T>,
69
pretty?: string,
70
exact?: boolean,
71
exportt?: boolean,
72
options?: Configuration
73
): Promise<T>;
74
75
/**
76
* Patch a Kubernetes object
77
* @param spec - Kubernetes object to patch
78
* @param pretty - Pretty-print the output
79
* @param dryRun - Dry run mode
80
* @param fieldManager - Field manager name
81
* @param force - Force the patch
82
* @param patchStrategy - Patch strategy to use
83
* @param options - Optional configuration options
84
* @returns Promise that resolves to patched object
85
*/
86
patch<T extends KubernetesObject>(
87
spec: T,
88
pretty?: string,
89
dryRun?: string,
90
fieldManager?: string,
91
force?: boolean,
92
patchStrategy?: PatchStrategy,
93
options?: Configuration
94
): Promise<T>;
95
96
/**
97
* Replace a Kubernetes object
98
* @param spec - Kubernetes object to replace
99
* @param pretty - Pretty-print the output
100
* @param dryRun - Dry run mode
101
* @param fieldManager - Field manager name
102
* @param options - Optional configuration options
103
* @returns Promise that resolves to replaced object
104
*/
105
replace<T extends KubernetesObject>(
106
spec: T,
107
pretty?: string,
108
dryRun?: string,
109
fieldManager?: string,
110
options?: Configuration
111
): Promise<T>;
112
113
/**
114
* List Kubernetes objects
115
* @param apiVersion - API version (e.g., 'v1', 'apps/v1')
116
* @param kind - Object kind (e.g., 'Pod', 'Deployment')
117
* @param namespace - Optional namespace filter
118
* @param pretty - Pretty-print the output
119
* @param allowWatchBookmarks - Allow watch bookmarks
120
* @param _continue - Continue token for pagination
121
* @param fieldSelector - Field selector for filtering
122
* @param labelSelector - Label selector for filtering
123
* @param limit - Maximum number of items to return
124
* @param resourceVersion - Resource version for consistency
125
* @param resourceVersionMatch - Resource version match strategy
126
* @param sendInitialEvents - Send initial events for watch
127
* @param timeoutSeconds - Request timeout
128
* @param watch - Watch for changes
129
* @returns Promise that resolves to object list
130
*/
131
list(
132
apiVersion: string,
133
kind: string,
134
namespace?: string,
135
pretty?: string,
136
allowWatchBookmarks?: boolean,
137
_continue?: string,
138
fieldSelector?: string,
139
labelSelector?: string,
140
limit?: number,
141
resourceVersion?: string,
142
resourceVersionMatch?: string,
143
sendInitialEvents?: boolean,
144
timeoutSeconds?: number,
145
watch?: boolean
146
): Promise<KubernetesObject>;
147
}
148
149
type KubernetesApiAction = 'create' | 'delete' | 'patch' | 'read' | 'list' | 'replace';
150
151
type KubernetesObjectHeader<T extends KubernetesObject> = Pick<T, 'apiVersion' | 'kind'> & {
152
metadata: {
153
name: string;
154
namespace?: string;
155
};
156
};
157
```
158
159
**Usage Examples:**
160
161
```typescript
162
import { KubeConfig, KubernetesObjectApi } from '@kubernetes/client-node';
163
164
const kc = new KubeConfig();
165
kc.loadFromDefault();
166
167
const k8sObjectApi = KubernetesObjectApi.makeApiClient(kc);
168
169
// Create any type of Kubernetes object
170
const createObject = async () => {
171
const configMap = {
172
apiVersion: 'v1',
173
kind: 'ConfigMap',
174
metadata: {
175
name: 'my-config',
176
namespace: 'default'
177
},
178
data: {
179
'config.json': JSON.stringify({ app: 'my-app', version: '1.0' })
180
}
181
};
182
183
try {
184
const created = await k8sObjectApi.create(configMap);
185
console.log('Created ConfigMap:', created.metadata?.name);
186
} catch (error) {
187
console.error('Failed to create ConfigMap:', error);
188
}
189
};
190
191
// Read any object by reference
192
const readObject = async () => {
193
const objectRef = {
194
apiVersion: 'v1',
195
kind: 'Pod',
196
metadata: {
197
name: 'my-pod',
198
namespace: 'default'
199
}
200
};
201
202
try {
203
const pod = await k8sObjectApi.read(objectRef);
204
console.log('Pod status:', pod.status?.phase);
205
} catch (error) {
206
console.error('Failed to read pod:', error);
207
}
208
};
209
210
// Patch objects with different strategies
211
const patchObject = async () => {
212
const objectRef = {
213
apiVersion: 'apps/v1',
214
kind: 'Deployment',
215
metadata: {
216
name: 'my-deployment',
217
namespace: 'default'
218
}
219
};
220
221
const patch = {
222
spec: {
223
replicas: 5
224
}
225
};
226
227
try {
228
const patched = await k8sObjectApi.patch(
229
objectRef,
230
patch,
231
undefined, // pretty
232
undefined, // dryRun
233
'my-controller' // fieldManager
234
);
235
console.log('Deployment scaled to:', patched.spec?.replicas);
236
} catch (error) {
237
console.error('Failed to patch deployment:', error);
238
}
239
};
240
241
// List objects of any type
242
const listObjects = async () => {
243
try {
244
const services = await k8sObjectApi.list(
245
'v1', // apiVersion
246
'Service', // kind
247
'default', // namespace
248
undefined, // pretty
249
undefined, // allowWatchBookmarks
250
undefined, // continue
251
undefined, // fieldSelector
252
'app=web' // labelSelector
253
);
254
255
console.log('Found services:', services.items?.length);
256
} catch (error) {
257
console.error('Failed to list services:', error);
258
}
259
};
260
261
// Delete objects with options
262
const deleteObject = async () => {
263
const objectRef = {
264
apiVersion: 'batch/v1',
265
kind: 'Job',
266
metadata: {
267
name: 'completed-job',
268
namespace: 'default'
269
}
270
};
271
272
try {
273
const status = await k8sObjectApi.delete(
274
objectRef,
275
undefined, // pretty
276
undefined, // dryRun
277
0, // gracePeriodSeconds (immediate deletion)
278
false, // orphanDependents
279
'Background' // propagationPolicy
280
);
281
console.log('Deletion status:', status.status);
282
} catch (error) {
283
console.error('Failed to delete job:', error);
284
}
285
};
286
287
// Generic object management functions
288
const manageCustomResource = async () => {
289
const customResource = {
290
apiVersion: 'apps.example.com/v1',
291
kind: 'MyApp',
292
metadata: {
293
name: 'my-app-instance',
294
namespace: 'production'
295
},
296
spec: {
297
replicas: 3,
298
image: 'my-app:v1.2.3',
299
environment: 'production'
300
}
301
};
302
303
try {
304
// Create
305
const created = await k8sObjectApi.create(customResource);
306
console.log('Custom resource created');
307
308
// Update
309
customResource.spec.replicas = 5;
310
const updated = await k8sObjectApi.replace(customResource);
311
console.log('Custom resource updated');
312
313
// Clean up
314
await k8sObjectApi.delete(customResource);
315
console.log('Custom resource deleted');
316
} catch (error) {
317
console.error('Custom resource management failed:', error);
318
}
319
};
320
```
321
322
### YAML Utilities
323
324
YAML parsing and serialization utilities for working with Kubernetes manifest files.
325
326
```typescript { .api }
327
/**
328
* Parse YAML string to JavaScript object
329
* @param data - YAML string to parse
330
* @param opts - YAML parsing options
331
* @returns Parsed object
332
*/
333
function loadYaml<T>(data: string, opts?: yaml.LoadOptions): T;
334
335
/**
336
* Parse multiple YAML documents from a single string
337
* @param data - YAML string containing multiple documents
338
* @param opts - YAML parsing options
339
* @returns Array of parsed objects
340
*/
341
function loadAllYaml(data: string, opts?: yaml.LoadOptions): any[];
342
343
/**
344
* Serialize JavaScript object to YAML string
345
* @param object - Object to serialize
346
* @param opts - YAML serialization options
347
* @returns YAML string
348
*/
349
function dumpYaml(object: any, opts?: yaml.DumpOptions): string;
350
```
351
352
**Usage Examples:**
353
354
```typescript
355
import { loadYaml, loadAllYaml, dumpYaml } from '@kubernetes/client-node';
356
import * as fs from 'fs';
357
358
// Load single YAML document
359
const loadManifest = () => {
360
const yamlContent = `
361
apiVersion: v1
362
kind: Pod
363
metadata:
364
name: my-pod
365
namespace: default
366
spec:
367
containers:
368
- name: app
369
image: nginx:latest
370
ports:
371
- containerPort: 80
372
`;
373
374
try {
375
const pod = loadYaml(yamlContent);
376
console.log('Loaded pod:', pod.metadata?.name);
377
return pod;
378
} catch (error) {
379
console.error('YAML parsing error:', error);
380
}
381
};
382
383
// Load multiple YAML documents
384
const loadMultipleManifests = () => {
385
const yamlContent = `
386
apiVersion: v1
387
kind: ConfigMap
388
metadata:
389
name: app-config
390
data:
391
app.conf: |
392
server_name = my-app
393
port = 8080
394
---
395
apiVersion: apps/v1
396
kind: Deployment
397
metadata:
398
name: my-app
399
spec:
400
replicas: 3
401
selector:
402
matchLabels:
403
app: my-app
404
template:
405
metadata:
406
labels:
407
app: my-app
408
spec:
409
containers:
410
- name: app
411
image: my-app:latest
412
`;
413
414
try {
415
const manifests = loadAllYaml(yamlContent);
416
console.log(`Loaded ${manifests.length} manifests`);
417
418
manifests.forEach((manifest, index) => {
419
console.log(`${index + 1}. ${manifest.kind}: ${manifest.metadata?.name}`);
420
});
421
422
return manifests;
423
} catch (error) {
424
console.error('Multi-YAML parsing error:', error);
425
}
426
};
427
428
// Load YAML from file
429
const loadManifestFromFile = async (filePath: string) => {
430
try {
431
const yamlContent = fs.readFileSync(filePath, 'utf8');
432
const manifest = loadYaml(yamlContent);
433
console.log('Loaded from file:', manifest.metadata?.name);
434
return manifest;
435
} catch (error) {
436
console.error('File loading error:', error);
437
}
438
};
439
440
// Convert objects to YAML
441
const exportToYaml = () => {
442
const deployment = {
443
apiVersion: 'apps/v1',
444
kind: 'Deployment',
445
metadata: {
446
name: 'web-server',
447
namespace: 'production',
448
labels: {
449
app: 'web-server',
450
version: 'v1.0'
451
}
452
},
453
spec: {
454
replicas: 3,
455
selector: {
456
matchLabels: {
457
app: 'web-server'
458
}
459
},
460
template: {
461
metadata: {
462
labels: {
463
app: 'web-server',
464
version: 'v1.0'
465
}
466
},
467
spec: {
468
containers: [{
469
name: 'web',
470
image: 'nginx:1.20',
471
ports: [{
472
containerPort: 80
473
}],
474
env: [{
475
name: 'ENVIRONMENT',
476
value: 'production'
477
}]
478
}]
479
}
480
}
481
}
482
};
483
484
try {
485
const yamlString = dumpYaml(deployment, {
486
indent: 2,
487
quotingType: '"',
488
forceQuotes: false
489
});
490
491
console.log('Generated YAML:');
492
console.log(yamlString);
493
494
// Save to file
495
fs.writeFileSync('./deployment.yaml', yamlString);
496
console.log('Saved to deployment.yaml');
497
498
} catch (error) {
499
console.error('YAML serialization error:', error);
500
}
501
};
502
503
// Process multiple manifest files
504
const processManifestDirectory = (dirPath: string) => {
505
const files = fs.readdirSync(dirPath)
506
.filter(file => file.endsWith('.yaml') || file.endsWith('.yml'));
507
508
const allManifests = [];
509
510
files.forEach(file => {
511
const filePath = `${dirPath}/${file}`;
512
const content = fs.readFileSync(filePath, 'utf8');
513
514
try {
515
const manifests = loadAllYaml(content);
516
allManifests.push(...manifests);
517
console.log(`Loaded ${manifests.length} manifests from ${file}`);
518
} catch (error) {
519
console.error(`Error processing ${file}:`, error);
520
}
521
});
522
523
return allManifests;
524
};
525
526
// Validate YAML structure
527
const validateKubernetesYaml = (yamlContent: string) => {
528
try {
529
const manifest = loadYaml(yamlContent);
530
531
// Basic validation
532
if (!manifest.apiVersion) {
533
throw new Error('Missing apiVersion');
534
}
535
if (!manifest.kind) {
536
throw new Error('Missing kind');
537
}
538
if (!manifest.metadata?.name) {
539
throw new Error('Missing metadata.name');
540
}
541
542
console.log('YAML validation passed');
543
return true;
544
} catch (error) {
545
console.error('YAML validation failed:', error.message);
546
return false;
547
}
548
};
549
```
550
551
### Patch Strategies
552
553
Constants and utilities for different Kubernetes patch strategies.
554
555
```typescript { .api }
556
/**
557
* Kubernetes patch strategy constants
558
*/
559
const PatchStrategy = {
560
/** JSON Patch (RFC 6902) */
561
JsonPatch: 'application/json-patch+json',
562
/** JSON Merge Patch (RFC 7396) */
563
MergePatch: 'application/merge-patch+json',
564
/** Strategic Merge Patch (Kubernetes-specific) */
565
StrategicMergePatch: 'application/strategic-merge-patch+json',
566
/** Server-Side Apply */
567
ServerSideApply: 'application/apply-patch+yaml'
568
} as const;
569
570
type PatchStrategy = typeof PatchStrategy[keyof typeof PatchStrategy];
571
```
572
573
**Usage Examples:**
574
575
```typescript
576
import { KubeConfig, CoreV1Api, PatchStrategy } from '@kubernetes/client-node';
577
578
const kc = new KubeConfig();
579
kc.loadFromDefault();
580
const k8sApi = kc.makeApiClient(CoreV1Api);
581
582
// JSON Patch (RFC 6902)
583
const jsonPatch = async () => {
584
const patch = [
585
{
586
op: 'replace',
587
path: '/spec/replicas',
588
value: 5
589
},
590
{
591
op: 'add',
592
path: '/metadata/labels/environment',
593
value: 'production'
594
}
595
];
596
597
try {
598
await k8sApi.patchNamespacedDeployment(
599
'my-deployment',
600
'default',
601
patch,
602
undefined, // pretty
603
undefined, // dryRun
604
undefined, // fieldManager
605
undefined, // fieldValidation
606
undefined, // force
607
{
608
headers: {
609
'Content-Type': PatchStrategy.JsonPatch
610
}
611
}
612
);
613
console.log('JSON Patch applied');
614
} catch (error) {
615
console.error('JSON Patch failed:', error);
616
}
617
};
618
619
// Strategic Merge Patch
620
const strategicMergePatch = async () => {
621
const patch = {
622
spec: {
623
template: {
624
spec: {
625
containers: [{
626
name: 'app',
627
env: [{
628
name: 'DEBUG',
629
value: 'true'
630
}]
631
}]
632
}
633
}
634
}
635
};
636
637
try {
638
await k8sApi.patchNamespacedDeployment(
639
'my-deployment',
640
'default',
641
patch,
642
undefined,
643
undefined,
644
undefined,
645
undefined,
646
undefined,
647
{
648
headers: {
649
'Content-Type': PatchStrategy.StrategicMergePatch
650
}
651
}
652
);
653
console.log('Strategic Merge Patch applied');
654
} catch (error) {
655
console.error('Strategic Merge Patch failed:', error);
656
}
657
};
658
659
// Merge Patch
660
const mergePatch = async () => {
661
const patch = {
662
metadata: {
663
labels: {
664
version: 'v2.0',
665
environment: 'staging'
666
}
667
}
668
};
669
670
try {
671
await k8sApi.patchNamespacedPod(
672
'my-pod',
673
'default',
674
patch,
675
undefined,
676
undefined,
677
undefined,
678
undefined,
679
undefined,
680
{
681
headers: {
682
'Content-Type': PatchStrategy.MergePatch
683
}
684
}
685
);
686
console.log('Merge Patch applied');
687
} catch (error) {
688
console.error('Merge Patch failed:', error);
689
}
690
};
691
692
// Server-Side Apply
693
const serverSideApply = async () => {
694
const manifest = {
695
apiVersion: 'v1',
696
kind: 'ConfigMap',
697
metadata: {
698
name: 'app-config',
699
namespace: 'default'
700
},
701
data: {
702
'app.properties': 'debug=true\nport=8080'
703
}
704
};
705
706
try {
707
await k8sApi.patchNamespacedConfigMap(
708
'app-config',
709
'default',
710
manifest,
711
undefined,
712
undefined,
713
'my-controller', // fieldManager is required
714
undefined,
715
true, // force
716
{
717
headers: {
718
'Content-Type': PatchStrategy.ServerSideApply
719
}
720
}
721
);
722
console.log('Server-Side Apply completed');
723
} catch (error) {
724
console.error('Server-Side Apply failed:', error);
725
}
726
};
727
```
728
729
### Health Checking
730
731
Health checking utilities for monitoring Kubernetes cluster readiness and liveness.
732
733
```typescript { .api }
734
/**
735
* Kubernetes cluster health checking
736
*/
737
class Health {
738
constructor(config: KubeConfig);
739
740
/**
741
* Check cluster readiness endpoint
742
* @param opts - Request options
743
* @returns Promise that resolves to readiness status
744
*/
745
readyz(opts: RequestOptions): Promise<boolean>;
746
747
/**
748
* Check cluster liveness endpoint
749
* @param opts - Request options
750
* @returns Promise that resolves to liveness status
751
*/
752
livez(opts: RequestOptions): Promise<boolean>;
753
}
754
755
interface RequestOptions {
756
/** Request timeout in milliseconds */
757
timeout?: number;
758
/** Additional headers */
759
headers?: Record<string, string>;
760
}
761
```
762
763
**Usage Examples:**
764
765
```typescript
766
import { KubeConfig, Health } from '@kubernetes/client-node';
767
768
const kc = new KubeConfig();
769
kc.loadFromDefault();
770
771
const health = new Health(kc);
772
773
// Check cluster readiness
774
const checkReadiness = async () => {
775
try {
776
const isReady = await health.readyz({ timeout: 5000 });
777
console.log('Cluster ready:', isReady);
778
return isReady;
779
} catch (error) {
780
console.error('Readiness check failed:', error);
781
return false;
782
}
783
};
784
785
// Check cluster liveness
786
const checkLiveness = async () => {
787
try {
788
const isLive = await health.livez({ timeout: 5000 });
789
console.log('Cluster live:', isLive);
790
return isLive;
791
} catch (error) {
792
console.error('Liveness check failed:', error);
793
return false;
794
}
795
};
796
797
// Continuous health monitoring
798
const monitorClusterHealth = () => {
799
const interval = setInterval(async () => {
800
try {
801
const [ready, live] = await Promise.all([
802
health.readyz({ timeout: 3000 }),
803
health.livez({ timeout: 3000 })
804
]);
805
806
const status = ready && live ? '✅ HEALTHY' : '❌ UNHEALTHY';
807
console.log(`Cluster status: ${status} (ready: ${ready}, live: ${live})`);
808
809
if (!ready || !live) {
810
console.warn('Cluster health issues detected');
811
}
812
813
} catch (error) {
814
console.error('Health check error:', error);
815
}
816
}, 30000); // Check every 30 seconds
817
818
// Stop monitoring on process exit
819
process.on('SIGINT', () => {
820
clearInterval(interval);
821
console.log('Health monitoring stopped');
822
process.exit(0);
823
});
824
};
825
826
// Health check with retries
827
const checkHealthWithRetry = async (maxRetries = 3) => {
828
for (let attempt = 1; attempt <= maxRetries; attempt++) {
829
try {
830
const [ready, live] = await Promise.all([
831
health.readyz({ timeout: 2000 }),
832
health.livez({ timeout: 2000 })
833
]);
834
835
if (ready && live) {
836
console.log(`Cluster healthy (attempt ${attempt})`);
837
return true;
838
}
839
840
console.warn(`Cluster unhealthy (attempt ${attempt}/${maxRetries})`);
841
842
} catch (error) {
843
console.error(`Health check attempt ${attempt} failed:`, error.message);
844
}
845
846
if (attempt < maxRetries) {
847
await new Promise(resolve => setTimeout(resolve, 1000));
848
}
849
}
850
851
console.error('Cluster health check failed after all retries');
852
return false;
853
};
854
```
855
856
### HTTP Middleware
857
858
HTTP request/response middleware utilities for customizing API client behavior.
859
860
```typescript { .api }
861
/**
862
* Create header middleware for HTTP requests
863
* @param key - Header name
864
* @param value - Header value
865
* @returns Observable middleware
866
*/
867
function setHeaderMiddleware(key: string, value: string): ObservableMiddleware;
868
869
/**
870
* Create header options for configuration
871
* @param key - Header name
872
* @param value - Header value
873
* @param opt - Optional existing configuration options
874
* @returns Configuration options with header middleware
875
*/
876
function setHeaderOptions(
877
key: string,
878
value: string,
879
opt?: ConfigurationOptions
880
): ConfigurationOptions;
881
```
882
883
**Usage Examples:**
884
885
```typescript
886
import {
887
KubeConfig,
888
CoreV1Api,
889
createConfiguration,
890
setHeaderMiddleware,
891
setHeaderOptions
892
} from '@kubernetes/client-node';
893
894
const kc = new KubeConfig();
895
kc.loadFromDefault();
896
897
// Add custom headers to all requests
898
const setupCustomHeaders = () => {
899
const headerOptions = setHeaderOptions('X-Custom-Header', 'my-value');
900
const config = createConfiguration(headerOptions);
901
902
// Use configuration with custom headers
903
const k8sApi = new CoreV1Api(config);
904
return k8sApi;
905
};
906
907
// Add multiple custom headers
908
const setupMultipleHeaders = () => {
909
let options = setHeaderOptions('X-Client-Version', '1.0.0');
910
options = setHeaderOptions('X-Environment', 'production', options);
911
options = setHeaderOptions('X-User-Agent', 'my-app/1.0', options);
912
913
const config = createConfiguration(options);
914
const k8sApi = new CoreV1Api(config);
915
return k8sApi;
916
};
917
918
// Custom middleware for request logging
919
const setupLoggingMiddleware = () => {
920
const loggingMiddleware = {
921
pre: (context) => {
922
console.log(`Making request to: ${context.url}`);
923
console.log(`Method: ${context.init.method || 'GET'}`);
924
return Promise.resolve(context);
925
},
926
post: (context) => {
927
console.log(`Response status: ${context.response.status}`);
928
return Promise.resolve(context);
929
}
930
};
931
932
const config = createConfiguration({
933
middleware: [loggingMiddleware]
934
});
935
936
const k8sApi = new CoreV1Api(config);
937
return k8sApi;
938
};
939
940
// Authentication middleware
941
const setupAuthMiddleware = (token: string) => {
942
const authMiddleware = {
943
pre: (context) => {
944
context.init.headers = {
945
...context.init.headers,
946
'Authorization': `Bearer ${token}`
947
};
948
return Promise.resolve(context);
949
}
950
};
951
952
const config = createConfiguration({
953
middleware: [authMiddleware]
954
});
955
956
return new CoreV1Api(config);
957
};
958
```
959
960
### Resource Utilities
961
962
Utility functions for working with Kubernetes resources, quantities, and common operations.
963
964
```typescript { .api }
965
/**
966
* Get all pods running on a specific node
967
* @param api - CoreV1Api instance
968
* @param nodeName - Name of the node
969
* @returns Promise that resolves to array of pods
970
*/
971
function podsForNode(api: CoreV1Api, nodeName: string): Promise<V1Pod[]>;
972
973
/**
974
* Convert Kubernetes quantity to scalar number
975
* @param quantity - Kubernetes quantity string (e.g., "100m", "1Gi")
976
* @returns Numeric value
977
*/
978
function quantityToScalar(quantity: string): number | bigint;
979
980
/**
981
* Extract unit suffix from quantity string
982
* @param quantity - Kubernetes quantity string
983
* @returns Unit suffix
984
*/
985
function findSuffix(quantity: string): string;
986
987
/**
988
* Utility function to add log options to URL search parameters
989
* @param options - Log streaming options
990
* @param searchParams - URLSearchParams object to modify
991
*/
992
function AddOptionsToSearchParams(options: LogOptions, searchParams: URLSearchParams): void;
993
```
994
995
**Usage Examples:**
996
997
```typescript
998
import {
999
KubeConfig,
1000
CoreV1Api,
1001
podsForNode,
1002
quantityToScalar,
1003
findSuffix
1004
} from '@kubernetes/client-node';
1005
1006
const kc = new KubeConfig();
1007
kc.loadFromDefault();
1008
const k8sApi = kc.makeApiClient(CoreV1Api);
1009
1010
// Get pods on specific node
1011
const getNodePods = async (nodeName: string) => {
1012
try {
1013
const pods = await podsForNode(k8sApi, nodeName);
1014
console.log(`Found ${pods.length} pods on node ${nodeName}`);
1015
1016
pods.forEach(pod => {
1017
console.log(`- ${pod.metadata?.name} (${pod.status?.phase})`);
1018
});
1019
1020
return pods;
1021
} catch (error) {
1022
console.error('Failed to get node pods:', error);
1023
}
1024
};
1025
1026
// Convert resource quantities
1027
const convertQuantities = () => {
1028
const quantities = ['100m', '1Gi', '500Mi', '2', '1.5'];
1029
1030
quantities.forEach(quantity => {
1031
const scalar = quantityToScalar(quantity);
1032
const suffix = findSuffix(quantity);
1033
1034
console.log(`${quantity}: ${scalar} (suffix: ${suffix})`);
1035
});
1036
};
1037
1038
// Analyze resource usage
1039
const analyzeResourceUsage = async () => {
1040
try {
1041
const nodes = await k8sApi.listNode();
1042
1043
for (const node of nodes.body.items) {
1044
const nodeName = node.metadata?.name;
1045
if (!nodeName) continue;
1046
1047
console.log(`\nNode: ${nodeName}`);
1048
1049
// Get node capacity
1050
const cpuCapacity = node.status?.capacity?.cpu;
1051
const memoryCapacity = node.status?.capacity?.memory;
1052
1053
if (cpuCapacity) {
1054
const cpuScalar = quantityToScalar(cpuCapacity);
1055
console.log(`CPU Capacity: ${cpuCapacity} (${cpuScalar} cores)`);
1056
}
1057
1058
if (memoryCapacity) {
1059
const memoryScalar = quantityToScalar(memoryCapacity);
1060
console.log(`Memory Capacity: ${memoryCapacity} (${memoryScalar} bytes)`);
1061
}
1062
1063
// Get pods on this node
1064
const pods = await podsForNode(k8sApi, nodeName);
1065
console.log(`Running Pods: ${pods.length}`);
1066
1067
// Calculate total requests/limits
1068
let totalCpuRequests = 0;
1069
let totalMemoryRequests = 0;
1070
1071
pods.forEach(pod => {
1072
pod.spec?.containers?.forEach(container => {
1073
const cpuRequest = container.resources?.requests?.cpu;
1074
const memoryRequest = container.resources?.requests?.memory;
1075
1076
if (cpuRequest) {
1077
totalCpuRequests += quantityToScalar(cpuRequest) as number;
1078
}
1079
if (memoryRequest) {
1080
totalMemoryRequests += quantityToScalar(memoryRequest) as number;
1081
}
1082
});
1083
});
1084
1085
console.log(`Total CPU Requests: ${totalCpuRequests}`);
1086
console.log(`Total Memory Requests: ${totalMemoryRequests}`);
1087
}
1088
} catch (error) {
1089
console.error('Resource analysis failed:', error);
1090
}
1091
};
1092
1093
// Utility for resource comparison
1094
const compareResources = (resource1: string, resource2: string) => {
1095
const scalar1 = quantityToScalar(resource1);
1096
const scalar2 = quantityToScalar(resource2);
1097
1098
if (scalar1 > scalar2) {
1099
return `${resource1} > ${resource2}`;
1100
} else if (scalar1 < scalar2) {
1101
return `${resource1} < ${resource2}`;
1102
} else {
1103
return `${resource1} = ${resource2}`;
1104
}
1105
};
1106
1107
// Example usage
1108
console.log(compareResources('1Gi', '1024Mi')); // Should be equal
1109
console.log(compareResources('500m', '1')); // 500m < 1
1110
```