Skip to content

Commit 596e9d7

Browse files
authored
fix(fluent): support deep partials for K8s().Apply() + return AbortController on K8s().Watch() (#8)
1 parent 0689025 commit 596e9d7

File tree

6 files changed

+48
-53
lines changed

6 files changed

+48
-53
lines changed

package-lock.json

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

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
"@kubernetes/client-node": "1.0.0-rc3",
3838
"fast-json-patch": "3.1.1",
3939
"http-status-codes": "2.3.0",
40-
"node-fetch": "2.7.0"
40+
"node-fetch": "2.7.0",
41+
"type-fest": "4.3.2"
4142
},
4243
"devDependencies": {
4344
"@commitlint/cli": "17.7.1",

src/fluent/index.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,18 @@ describe("Kube", () => {
133133
const kube = K8s(Pod);
134134
await expect(kube.Patch([])).rejects.toThrow("No operations specified");
135135
});
136+
137+
it("should allow Apply of deep partials", async () => {
138+
const kube = K8s(Pod);
139+
const result = await kube.Apply({ metadata: { name: "fake" }, spec: { priority: 3 } });
140+
expect(result).toEqual(fakeResource);
141+
});
142+
143+
it("should throw an error if a Delete failed for a reason other than Not Found", async () => {
144+
mockedKubeExec.mockRejectedValueOnce({ status: 500 }); // Internal Server Error on first call
145+
const kube = K8s(Pod);
146+
await expect(kube.Delete("fakeResource")).rejects.toEqual(
147+
expect.objectContaining({ status: 500 }),
148+
);
149+
});
136150
});

src/fluent/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { KubernetesListObject, KubernetesObject } from "@kubernetes/client-node";
55
import { Operation } from "fast-json-patch";
66
import { StatusCodes } from "http-status-codes";
7+
import type { PartialDeep } from "type-fest";
78

89
import { modelToGroupVersionKind } from "../kinds";
910
import { GenericClass } from "../types";
@@ -99,8 +100,8 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
99100
}
100101
}
101102

102-
async function Apply(resource: K): Promise<K> {
103-
syncFilters(resource);
103+
async function Apply(resource: PartialDeep<K>): Promise<K> {
104+
syncFilters(resource as K);
104105
return k8sExec(model, filters, "APPLY", resource);
105106
}
106107

@@ -118,8 +119,8 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
118119
return k8sExec<T, K>(model, filters, "PATCH", payload);
119120
}
120121

121-
async function Watch(callback: WatchAction<T>): Promise<void> {
122-
await ExecWatch(model, filters, callback);
122+
async function Watch(callback: WatchAction<T>): Promise<AbortController> {
123+
return ExecWatch(model, filters, callback);
123124
}
124125

125126
return { InNamespace, Apply, Create, Patch, ...withFilters };

src/fluent/types.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import { KubernetesListObject, KubernetesObject } from "@kubernetes/client-node";
55
import { Operation } from "fast-json-patch";
6+
import type { PartialDeep } from "type-fest";
67

78
import { GenericClass, GroupVersionKind } from "../types";
89

@@ -50,7 +51,7 @@ export type K8sFilteredActions<K extends KubernetesObject> = {
5051
* @param callback
5152
* @returns
5253
*/
53-
Watch: (callback: (payload: K, phase: WatchPhase) => void) => Promise<void>;
54+
Watch: (callback: (payload: K, phase: WatchPhase) => void) => Promise<AbortController>;
5455
};
5556

5657
export type K8sUnfilteredActions<K extends KubernetesObject> = {
@@ -60,7 +61,7 @@ export type K8sUnfilteredActions<K extends KubernetesObject> = {
6061
* @param resource
6162
* @returns
6263
*/
63-
Apply: (resource: K) => Promise<K>;
64+
Apply: (resource: PartialDeep<K>) => Promise<K>;
6465

6566
/**
6667
* Create the provided K8s resource or throw an error if it already exists.
@@ -71,7 +72,7 @@ export type K8sUnfilteredActions<K extends KubernetesObject> = {
7172
Create: (resource: K) => Promise<K>;
7273

7374
/**
74-
* Advanced JSON Patch operations for when Server Side Apply, Kube().Apply(), is insufficient.
75+
* Advanced JSON Patch operations for when Server Side Apply, K8s().Apply(), is insufficient.
7576
*
7677
* Note: Throws an error on an empty list of patch operations.
7778
*
@@ -87,7 +88,7 @@ export type K8sWithFilters<K extends KubernetesObject> = K8sFilteredActions<K> &
8788
* Note multiple calls to this method will result in an AND condition. e.g.
8889
*
8990
* ```ts
90-
* Kube(given.Deployment)
91+
* K8s(kind.Deployment)
9192
* .WithField("metadata.name", "bar")
9293
* .WithField("metadata.namespace", "qux")
9394
* .Delete(...)
@@ -106,7 +107,7 @@ export type K8sWithFilters<K extends KubernetesObject> = K8sFilteredActions<K> &
106107
* Note multiple calls to this method will result in an AND condition. e.g.
107108
*
108109
* ```ts
109-
* Kube(given.Deployment)
110+
* K8s(kind.Deployment)
110111
* .WithLabel("foo", "bar")
111112
* .WithLabel("baz", "qux")
112113
* .Delete(...)

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ export { K8s } from "./fluent";
2020
export { RegisterKind, modelToGroupVersionKind } from "./kinds";
2121

2222
export * from "./types";
23+
24+
export * as K8sClientNode from "@kubernetes/client-node";

0 commit comments

Comments
 (0)