Skip to content

Commit d292a4d

Browse files
author
David Dooling
committed
Add KubernetesObjectApi
Add generic object API that dynamically determines endpoint based on the provided spec. Add KubernetesObjectApi to index exports. Provide tests and example usage. Closes #375
1 parent e150480 commit d292a4d

File tree

4 files changed

+2401
-0
lines changed

4 files changed

+2401
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import * as k8s from '@kubernetes/client-node';
2+
import * as fs from 'fs';
3+
import * as yaml from 'js-yaml';
4+
import { promisify } from 'util';
5+
6+
/**
7+
* Replicate the functionality of `kubectl apply`. That is, create the resources defined in the `specFile` if they do
8+
* not exist, patch them if they do exist.
9+
*
10+
* @param specPath File system path to a YAML Kubernetes spec.
11+
* @return Array of resources created
12+
*/
13+
export async function apply(specPath: string): Promise<k8s.KubernetesObject[]> {
14+
const kc = new k8s.KubeConfig();
15+
kc.loadFromDefault();
16+
const client = k8s.KubernetesObjectApi.makeApiClient(kc);
17+
const fsReadFileP = promisify(fs.readFile);
18+
const specString = await fsReadFileP(specPath, 'utf8');
19+
const specs: k8s.KubernetesObject[] = yaml.safeLoadAll(specString);
20+
const validSpecs = specs.filter((s) => s && s.kind && s.metadata);
21+
const created: k8s.KubernetesObject[] = [];
22+
for (const spec of validSpecs) {
23+
// this is to convince the old version of TypeScript that metadata exists even though we already filtered specs
24+
// without metadata out
25+
spec.metadata = spec.metadata || {};
26+
spec.metadata.annotations = spec.metadata.annotations || {};
27+
delete spec.metadata.annotations['kubectl.kubernetes.io/last-applied-configuration'];
28+
spec.metadata.annotations['kubectl.kubernetes.io/last-applied-configuration'] = JSON.stringify(spec);
29+
try {
30+
// try to get the resource, if it does not exist an error will be thrown and we will end up in the catch
31+
// block.
32+
await client.read(spec);
33+
// we got the resource, so it exists, so patch it
34+
const response = await client.patch(spec);
35+
created.push(response.body);
36+
} catch (e) {
37+
// we did not get the resource, so it does not exist, so create it
38+
const response = await client.create(spec);
39+
created.push(response.body);
40+
}
41+
}
42+
return created;
43+
}

src/index.ts

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

0 commit comments

Comments
 (0)