kubernetes-fluent-client 1.3.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fluent/index.js +2 -2
- package/dist/fluent/types.d.ts +2 -2
- package/dist/fluent/types.d.ts.map +1 -1
- package/dist/fluent/utils.d.ts.map +1 -1
- package/dist/fluent/utils.js +2 -0
- package/dist/fluent/watch.d.ts +39 -2
- package/dist/fluent/watch.d.ts.map +1 -1
- package/dist/fluent/watch.js +103 -47
- package/dist/kinds.d.ts.map +1 -1
- package/dist/kinds.js +13 -0
- package/dist/kinds.test.js +4 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -2
- package/src/fluent/index.ts +3 -3
- package/src/fluent/types.ts +5 -1
- package/src/fluent/utils.ts +3 -0
- package/src/fluent/watch.ts +172 -57
- package/src/kinds.test.ts +4 -0
- package/src/kinds.ts +14 -0
- package/src/types.ts +7 -0
- package/__mocks__/@kubernetes/client-node.ts +0 -22
- package/commitlint.config.js +0 -1
package/dist/fluent/index.js
CHANGED
|
@@ -92,8 +92,8 @@ function K8s(model, filters = {}) {
|
|
|
92
92
|
}
|
|
93
93
|
return (0, utils_1.k8sExec)(model, filters, "PATCH", payload);
|
|
94
94
|
}
|
|
95
|
-
async function Watch(callback) {
|
|
96
|
-
return (0, watch_1.ExecWatch)(model, filters, callback);
|
|
95
|
+
async function Watch(callback, watchCfg) {
|
|
96
|
+
return (0, watch_1.ExecWatch)(model, filters, callback, watchCfg);
|
|
97
97
|
}
|
|
98
98
|
return { InNamespace, Apply, Create, Patch, ...withFilters };
|
|
99
99
|
}
|
package/dist/fluent/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { KubernetesListObject, KubernetesObject } from "@kubernetes/client-node";
|
|
3
2
|
import { Operation } from "fast-json-patch";
|
|
4
3
|
import type { PartialDeep } from "type-fest";
|
|
5
4
|
import { GenericClass, GroupVersionKind } from "../types";
|
|
5
|
+
import { WatchCfg, WatchController } from "./watch";
|
|
6
6
|
/**
|
|
7
7
|
* The Phase matched when using the K8s Watch API.
|
|
8
8
|
*/
|
|
@@ -41,7 +41,7 @@ export type K8sFilteredActions<K extends KubernetesObject> = {
|
|
|
41
41
|
* @param callback
|
|
42
42
|
* @returns
|
|
43
43
|
*/
|
|
44
|
-
Watch: (callback: (payload: K, phase: WatchPhase) => void) => Promise<
|
|
44
|
+
Watch: (callback: (payload: K, phase: WatchPhase) => void, watchCfg?: WatchCfg) => Promise<WatchController>;
|
|
45
45
|
};
|
|
46
46
|
export type K8sUnfilteredActions<K extends KubernetesObject> = {
|
|
47
47
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/fluent/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/fluent/types.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEpD;;GAEG;AACH,oBAAY,UAAU;IACpB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,OAAO,YAAY;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAE3F,MAAM,WAAW,OAAO;IACtB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,gBAAgB,IAAI;IACpD,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,gBAAgB,IAAI;IAC3D;;;;OAIG;IACH,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAEpB;;;;OAIG;IACH,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C;;;;OAIG;IACH,KAAK,EAAE,CACL,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,KAAK,IAAI,EACjD,QAAQ,CAAC,EAAE,QAAQ,KAChB,OAAO,CAAC,eAAe,CAAC,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,gBAAgB,IAAI;IAC7D;;;;;OAKG;IACH,KAAK,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAEhD;;;;;OAKG;IACH,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAEpC;;;;;;;OAOG;IACH,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,gBAAgB,IAAI,kBAAkB,CAAC,CAAC,CAAC,GAAG;IAC/E;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,EAAE,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC;IAE7E;;;;;;;;;;;;;;;OAeG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,gBAAgB,IAAI,cAAc,CAAC,CAAC,CAAC,GACjE,oBAAoB,CAAC,CAAC,CAAC,GAAG;IACxB;;;;;OAKG;IACH,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC;CACvD,CAAC;AAEJ,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,gBAAgB,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,CAC9F,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,UAAU,KACd,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAG1B,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,MAAM,GAAG,MAAM,GACvC,CAAC,SAAS,MAAM,GAAG,MAAM,GACvB,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAAC,EAAE,GACpC,KAAK,GACP,KAAK,CAAC;AAEV,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC7D,KAAK,GACL,CAAC,SAAS,MAAM,GAChB;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK;CAAE,CAAC,MAAM,CAAC,CAAC,GAChG,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/fluent/utils.ts"],"names":[],"mappings":";AAMA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAG1B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIhD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,YAAY,EAChD,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,OAAO,EAChB,WAAW,UAAQ,OAsDpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY;;;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/fluent/utils.ts"],"names":[],"mappings":";AAMA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAG1B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIhD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,YAAY,EAChD,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,OAAO,EAChB,WAAW,UAAQ,OAsDpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY;;;GAwBhD;AAED,wBAAsB,OAAO,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,EACrD,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,CAAC,GAAG,OAAO,cA8BtB"}
|
package/dist/fluent/utils.js
CHANGED
package/dist/fluent/watch.d.ts
CHANGED
|
@@ -1,8 +1,45 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { GenericClass } from "../types";
|
|
2
|
+
import { GenericClass, LogFn } from "../types";
|
|
3
3
|
import { Filters, WatchAction } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* Wrapper for the AbortController to allow the watch to be aborted externally.
|
|
6
|
+
*/
|
|
7
|
+
export type WatchController = {
|
|
8
|
+
/**
|
|
9
|
+
* Abort the watch.
|
|
10
|
+
* @param reason optional reason for aborting the watch
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
abort: (reason?: string) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Get the AbortSignal for the watch.
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
signal: () => AbortSignal;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for the watch function.
|
|
22
|
+
*/
|
|
23
|
+
export type WatchCfg = {
|
|
24
|
+
/**
|
|
25
|
+
* The maximum number of times to retry the watch, the retry count is reset on success.
|
|
26
|
+
*/
|
|
27
|
+
retryMax?: number;
|
|
28
|
+
/**
|
|
29
|
+
* The delay between retries in seconds.
|
|
30
|
+
*/
|
|
31
|
+
retryDelaySec?: number;
|
|
32
|
+
/**
|
|
33
|
+
* A function to log errors.
|
|
34
|
+
*/
|
|
35
|
+
logFn?: LogFn;
|
|
36
|
+
/**
|
|
37
|
+
* A function to call when the watch fails after the maximum number of retries.
|
|
38
|
+
*/
|
|
39
|
+
retryFail?: (e: Error) => void;
|
|
40
|
+
};
|
|
4
41
|
/**
|
|
5
42
|
* Execute a watch on the specified resource.
|
|
6
43
|
*/
|
|
7
|
-
export declare function ExecWatch<T extends GenericClass>(model: T, filters: Filters, callback: WatchAction<T
|
|
44
|
+
export declare function ExecWatch<T extends GenericClass>(model: T, filters: Filters, callback: WatchAction<T>, watchCfg?: WatchCfg): Promise<WatchController>;
|
|
8
45
|
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/fluent/watch.ts"],"names":[],"mappings":";AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/fluent/watch.ts"],"names":[],"mappings":";AAMA,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAc,MAAM,SAAS,CAAC;AAG3D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;OAIG;IACH,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC;;;OAGG;IACH,MAAM,EAAE,MAAM,WAAW,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC,CAAC;AAEF;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,SAAS,YAAY,EACpD,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,EACxB,QAAQ,GAAE,QAAa,4BAwJxB"}
|
package/dist/fluent/watch.js
CHANGED
|
@@ -6,13 +6,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6
6
|
};
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.ExecWatch = void 0;
|
|
9
|
-
const
|
|
9
|
+
const byline_1 = __importDefault(require("byline"));
|
|
10
10
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
11
11
|
const utils_1 = require("./utils");
|
|
12
12
|
/**
|
|
13
13
|
* Execute a watch on the specified resource.
|
|
14
14
|
*/
|
|
15
|
-
async function ExecWatch(model, filters, callback) {
|
|
15
|
+
async function ExecWatch(model, filters, callback, watchCfg = {}) {
|
|
16
|
+
watchCfg.logFn?.({ model, filters, watchCfg }, "ExecWatch");
|
|
16
17
|
// Build the path and query params for the resource, excluding the name
|
|
17
18
|
const { opts, serverUrl } = await (0, utils_1.k8sCfg)("GET");
|
|
18
19
|
const url = (0, utils_1.pathBuilder)(serverUrl, model, filters, true);
|
|
@@ -24,55 +25,110 @@ async function ExecWatch(model, filters, callback) {
|
|
|
24
25
|
if (filters.name) {
|
|
25
26
|
url.searchParams.set("fieldSelector", `metadata.name=${filters.name}`);
|
|
26
27
|
}
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
28
|
+
// Set the initial timeout to 15 seconds
|
|
29
|
+
opts.timeout = 15 * 1000;
|
|
30
|
+
// Enable keep alive
|
|
31
|
+
opts.agent.keepAlive = true;
|
|
32
|
+
// Track the number of retries
|
|
33
|
+
let retryCount = 0;
|
|
34
|
+
// Set the maximum number of retries to 5 if not specified
|
|
35
|
+
watchCfg.retryMax ??= 5;
|
|
36
|
+
// Set the retry delay to 5 seconds if not specified
|
|
37
|
+
watchCfg.retryDelaySec ??= 5;
|
|
38
|
+
// Create a throwaway AbortController to setup the wrapped AbortController
|
|
39
|
+
let abortController;
|
|
40
|
+
// Create a wrapped AbortController to allow the watch to be aborted externally
|
|
41
|
+
const abortWrapper = {};
|
|
42
|
+
function bindAbortController() {
|
|
43
|
+
// Create a new AbortController
|
|
44
|
+
abortController = new AbortController();
|
|
45
|
+
// Update the abort wrapper
|
|
46
|
+
abortWrapper.abort = reason => abortController.abort(reason);
|
|
47
|
+
abortWrapper.signal = () => abortController.signal;
|
|
48
|
+
// Add the abort signal to the request options
|
|
49
|
+
opts.signal = abortController.signal;
|
|
50
|
+
}
|
|
51
|
+
async function runner() {
|
|
52
|
+
let doneCalled = false;
|
|
53
|
+
bindAbortController();
|
|
54
|
+
// Create a stream to read the response body
|
|
55
|
+
const stream = byline_1.default.createStream();
|
|
56
|
+
const onError = (err) => {
|
|
57
|
+
stream.removeAllListeners();
|
|
58
|
+
if (!doneCalled) {
|
|
59
|
+
doneCalled = true;
|
|
60
|
+
// If the error is not an AbortError, reload the watch
|
|
61
|
+
if (err.name !== "AbortError") {
|
|
62
|
+
watchCfg.logFn?.(err, "stream error");
|
|
63
|
+
void reload(err);
|
|
60
64
|
}
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
else {
|
|
66
|
+
watchCfg.logFn?.("watch aborted via WatchController.abort()");
|
|
63
67
|
}
|
|
64
|
-
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const cleanup = () => {
|
|
71
|
+
if (!doneCalled) {
|
|
72
|
+
doneCalled = true;
|
|
73
|
+
stream.removeAllListeners();
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
try {
|
|
77
|
+
// Make the actual request
|
|
78
|
+
const response = await (0, node_fetch_1.default)(url, { ...opts });
|
|
79
|
+
// If the request is successful, start listening for events
|
|
80
|
+
if (response.ok) {
|
|
81
|
+
const { body } = response;
|
|
82
|
+
// Reset the retry count
|
|
83
|
+
retryCount = 0;
|
|
84
|
+
stream.on("error", onError);
|
|
85
|
+
stream.on("close", cleanup);
|
|
86
|
+
stream.on("finish", cleanup);
|
|
87
|
+
// Listen for events and call the callback function
|
|
88
|
+
stream.on("data", line => {
|
|
89
|
+
try {
|
|
90
|
+
// Parse the event payload
|
|
91
|
+
const { object: payload, type: phase } = JSON.parse(line);
|
|
92
|
+
// Call the callback function with the parsed payload
|
|
93
|
+
void callback(payload, phase);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
watchCfg.logFn?.(err, "watch callback error");
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
body.on("error", onError);
|
|
100
|
+
body.on("close", cleanup);
|
|
101
|
+
body.on("finish", cleanup);
|
|
102
|
+
// Pipe the response body to the stream
|
|
103
|
+
body.pipe(stream);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
throw new Error(`watch failed: ${response.status} ${response.statusText}`);
|
|
107
|
+
}
|
|
65
108
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
109
|
+
catch (e) {
|
|
110
|
+
onError(e);
|
|
111
|
+
}
|
|
112
|
+
// On unhandled errors, retry the watch
|
|
113
|
+
async function reload(e) {
|
|
114
|
+
// If there are more attempts, retry the watch
|
|
115
|
+
if (watchCfg.retryMax > retryCount) {
|
|
116
|
+
retryCount++;
|
|
117
|
+
watchCfg.logFn?.(`retrying watch ${retryCount}/${watchCfg.retryMax}`);
|
|
118
|
+
// Sleep for the specified delay or 5 seconds
|
|
119
|
+
await new Promise(r => setTimeout(r, watchCfg.retryDelaySec * 1000));
|
|
120
|
+
// Retry the watch after the delay
|
|
121
|
+
await runner();
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Otherwise, call the finally function if it exists
|
|
125
|
+
if (watchCfg.retryFail) {
|
|
126
|
+
watchCfg.retryFail(e);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
71
129
|
}
|
|
72
130
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
return controller;
|
|
131
|
+
await runner();
|
|
132
|
+
return abortWrapper;
|
|
77
133
|
}
|
|
78
134
|
exports.ExecWatch = ExecWatch;
|
package/dist/kinds.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kinds.d.ts","sourceRoot":"","sources":["../src/kinds.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"kinds.d.ts","sourceRoot":"","sources":["../src/kinds.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAwgBzD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAErE;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,UAAW,YAAY,oBAAoB,gBAAgB,SAUnF,CAAC"}
|
package/dist/kinds.js
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.RegisterKind = exports.modelToGroupVersionKind = void 0;
|
|
6
6
|
const gvkMap = {
|
|
7
|
+
/**
|
|
8
|
+
* Represents a K8s Event resource.
|
|
9
|
+
* Event is a report of an event somewhere in the cluster. It generally denotes some state change in the system.
|
|
10
|
+
* Events have a limited retention time and triggers and messages may evolve with time. Event consumers should not
|
|
11
|
+
* rely on the timing of an event with a given Reason reflecting a consistent underlying trigger, or the continued
|
|
12
|
+
* existence of events with that Reason. Events should be treated as informative, best-effort, supplemental data.
|
|
13
|
+
* @see {@link https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/event-v1/}
|
|
14
|
+
*/
|
|
15
|
+
CoreV1Event: {
|
|
16
|
+
kind: "Event",
|
|
17
|
+
version: "v1",
|
|
18
|
+
group: "events.k8s.io",
|
|
19
|
+
},
|
|
7
20
|
/**
|
|
8
21
|
* Represents a K8s ClusterRole resource.
|
|
9
22
|
* ClusterRole is a set of permissions that can be bound to a user or group in a cluster-wide scope.
|
package/dist/kinds.test.js
CHANGED
|
@@ -6,6 +6,10 @@ const globals_1 = require("@jest/globals");
|
|
|
6
6
|
const index_1 = require("./index");
|
|
7
7
|
const kinds_1 = require("./kinds");
|
|
8
8
|
const testCases = [
|
|
9
|
+
{
|
|
10
|
+
name: index_1.kind.Event,
|
|
11
|
+
expected: { group: "events.k8s.io", version: "v1", kind: "Event" },
|
|
12
|
+
},
|
|
9
13
|
{
|
|
10
14
|
name: index_1.kind.ClusterRole,
|
|
11
15
|
expected: { group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole" },
|
package/dist/types.d.ts
CHANGED
|
@@ -24,4 +24,9 @@ export interface GroupVersionKind {
|
|
|
24
24
|
/** Optional, override the plural name for use in Webhook rules generation */
|
|
25
25
|
readonly plural?: string;
|
|
26
26
|
}
|
|
27
|
+
export interface LogFn {
|
|
28
|
+
<T extends object>(obj: T, msg?: string, ...args: never[]): void;
|
|
29
|
+
(obj: unknown, msg?: string, ...args: never[]): void;
|
|
30
|
+
(msg: string, ...args: never[]): void;
|
|
31
|
+
}
|
|
27
32
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAGjF,MAAM,MAAM,YAAY,GAAG,QAAQ,WAAW,GAAG,CAAC;AAElD;;;;GAIG;AACH,qBAAa,WAAY,YAAW,gBAAgB;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,YAAY,CAAC;IAExB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;;IAGI;AACJ,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAGjF,MAAM,MAAM,YAAY,GAAG,QAAQ,WAAW,GAAG,CAAC;AAElD;;;;GAIG;AACH,qBAAa,WAAY,YAAW,gBAAgB;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,YAAY,CAAC;IAExB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;;IAGI;AACJ,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,KAAK;IAEpB,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IACjE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IACrD,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;CACvC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kubernetes-fluent-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A @kubernetes/client-node fluent API wrapper that leverages K8s Server Side Apply",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -35,15 +35,17 @@
|
|
|
35
35
|
"homepage": "https://github.com/defenseunicorns/kubernetes-fluent-client#readme",
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@kubernetes/client-node": "1.0.0-rc3",
|
|
38
|
+
"byline": "5.0.0",
|
|
38
39
|
"fast-json-patch": "3.1.1",
|
|
39
40
|
"http-status-codes": "2.3.0",
|
|
40
41
|
"node-fetch": "2.7.0",
|
|
41
42
|
"type-fest": "4.3.2"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
|
-
"@commitlint/cli": "17.7.
|
|
45
|
+
"@commitlint/cli": "17.7.2",
|
|
45
46
|
"@commitlint/config-conventional": "17.7.0",
|
|
46
47
|
"@jest/globals": "29.7.0",
|
|
48
|
+
"@types/byline": "4.2.34",
|
|
47
49
|
"@typescript-eslint/eslint-plugin": "6.7.3",
|
|
48
50
|
"@typescript-eslint/parser": "6.7.3",
|
|
49
51
|
"jest": "29.7.0",
|
package/src/fluent/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { modelToGroupVersionKind } from "../kinds";
|
|
|
10
10
|
import { GenericClass } from "../types";
|
|
11
11
|
import { Filters, K8sInit, Paths, WatchAction } from "./types";
|
|
12
12
|
import { k8sExec } from "./utils";
|
|
13
|
-
import { ExecWatch } from "./watch";
|
|
13
|
+
import { ExecWatch, WatchCfg } from "./watch";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Kubernetes fluent API inspired by Kubectl. Pass in a model, then call filters and actions on it.
|
|
@@ -119,8 +119,8 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
119
119
|
return k8sExec<T, K>(model, filters, "PATCH", payload);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
async function Watch(callback: WatchAction<T
|
|
123
|
-
return ExecWatch(model, filters, callback);
|
|
122
|
+
async function Watch(callback: WatchAction<T>, watchCfg?: WatchCfg) {
|
|
123
|
+
return ExecWatch(model, filters, callback, watchCfg);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
return { InNamespace, Apply, Create, Patch, ...withFilters };
|
package/src/fluent/types.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Operation } from "fast-json-patch";
|
|
|
6
6
|
import type { PartialDeep } from "type-fest";
|
|
7
7
|
|
|
8
8
|
import { GenericClass, GroupVersionKind } from "../types";
|
|
9
|
+
import { WatchCfg, WatchController } from "./watch";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* The Phase matched when using the K8s Watch API.
|
|
@@ -51,7 +52,10 @@ export type K8sFilteredActions<K extends KubernetesObject> = {
|
|
|
51
52
|
* @param callback
|
|
52
53
|
* @returns
|
|
53
54
|
*/
|
|
54
|
-
Watch: (
|
|
55
|
+
Watch: (
|
|
56
|
+
callback: (payload: K, phase: WatchPhase) => void,
|
|
57
|
+
watchCfg?: WatchCfg,
|
|
58
|
+
) => Promise<WatchController>;
|
|
55
59
|
};
|
|
56
60
|
|
|
57
61
|
export type K8sUnfilteredActions<K extends KubernetesObject> = {
|
package/src/fluent/utils.ts
CHANGED
package/src/fluent/watch.ts
CHANGED
|
@@ -1,13 +1,52 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
3
|
|
|
4
|
-
import
|
|
5
|
-
|
|
4
|
+
import byline from "byline";
|
|
6
5
|
import fetch from "node-fetch";
|
|
7
|
-
|
|
6
|
+
|
|
7
|
+
import { GenericClass, LogFn } from "../types";
|
|
8
8
|
import { Filters, WatchAction, WatchPhase } from "./types";
|
|
9
9
|
import { k8sCfg, pathBuilder } from "./utils";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Wrapper for the AbortController to allow the watch to be aborted externally.
|
|
13
|
+
*/
|
|
14
|
+
export type WatchController = {
|
|
15
|
+
/**
|
|
16
|
+
* Abort the watch.
|
|
17
|
+
* @param reason optional reason for aborting the watch
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
abort: (reason?: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Get the AbortSignal for the watch.
|
|
23
|
+
* @returns
|
|
24
|
+
*/
|
|
25
|
+
signal: () => AbortSignal;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for the watch function.
|
|
30
|
+
*/
|
|
31
|
+
export type WatchCfg = {
|
|
32
|
+
/**
|
|
33
|
+
* The maximum number of times to retry the watch, the retry count is reset on success.
|
|
34
|
+
*/
|
|
35
|
+
retryMax?: number;
|
|
36
|
+
/**
|
|
37
|
+
* The delay between retries in seconds.
|
|
38
|
+
*/
|
|
39
|
+
retryDelaySec?: number;
|
|
40
|
+
/**
|
|
41
|
+
* A function to log errors.
|
|
42
|
+
*/
|
|
43
|
+
logFn?: LogFn;
|
|
44
|
+
/**
|
|
45
|
+
* A function to call when the watch fails after the maximum number of retries.
|
|
46
|
+
*/
|
|
47
|
+
retryFail?: (e: Error) => void;
|
|
48
|
+
};
|
|
49
|
+
|
|
11
50
|
/**
|
|
12
51
|
* Execute a watch on the specified resource.
|
|
13
52
|
*/
|
|
@@ -15,7 +54,10 @@ export async function ExecWatch<T extends GenericClass>(
|
|
|
15
54
|
model: T,
|
|
16
55
|
filters: Filters,
|
|
17
56
|
callback: WatchAction<T>,
|
|
57
|
+
watchCfg: WatchCfg = {},
|
|
18
58
|
) {
|
|
59
|
+
watchCfg.logFn?.({ model, filters, watchCfg }, "ExecWatch");
|
|
60
|
+
|
|
19
61
|
// Build the path and query params for the resource, excluding the name
|
|
20
62
|
const { opts, serverUrl } = await k8sCfg("GET");
|
|
21
63
|
const url = pathBuilder(serverUrl, model, filters, true);
|
|
@@ -31,64 +73,137 @@ export async function ExecWatch<T extends GenericClass>(
|
|
|
31
73
|
url.searchParams.set("fieldSelector", `metadata.name=${filters.name}`);
|
|
32
74
|
}
|
|
33
75
|
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
76
|
+
// Set the initial timeout to 15 seconds
|
|
77
|
+
opts.timeout = 15 * 1000;
|
|
78
|
+
|
|
79
|
+
// Enable keep alive
|
|
80
|
+
(opts.agent as unknown as { keepAlive: boolean }).keepAlive = true;
|
|
81
|
+
|
|
82
|
+
// Track the number of retries
|
|
83
|
+
let retryCount = 0;
|
|
84
|
+
|
|
85
|
+
// Set the maximum number of retries to 5 if not specified
|
|
86
|
+
watchCfg.retryMax ??= 5;
|
|
87
|
+
|
|
88
|
+
// Set the retry delay to 5 seconds if not specified
|
|
89
|
+
watchCfg.retryDelaySec ??= 5;
|
|
90
|
+
|
|
91
|
+
// Create a throwaway AbortController to setup the wrapped AbortController
|
|
92
|
+
let abortController: AbortController;
|
|
93
|
+
|
|
94
|
+
// Create a wrapped AbortController to allow the watch to be aborted externally
|
|
95
|
+
const abortWrapper = {} as WatchController;
|
|
96
|
+
|
|
97
|
+
function bindAbortController() {
|
|
98
|
+
// Create a new AbortController
|
|
99
|
+
abortController = new AbortController();
|
|
100
|
+
|
|
101
|
+
// Update the abort wrapper
|
|
102
|
+
abortWrapper.abort = reason => abortController.abort(reason);
|
|
103
|
+
abortWrapper.signal = () => abortController.signal;
|
|
104
|
+
|
|
105
|
+
// Add the abort signal to the request options
|
|
106
|
+
opts.signal = abortController.signal;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function runner() {
|
|
110
|
+
let doneCalled = false;
|
|
37
111
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
112
|
+
bindAbortController();
|
|
113
|
+
|
|
114
|
+
// Create a stream to read the response body
|
|
115
|
+
const stream = byline.createStream();
|
|
116
|
+
|
|
117
|
+
const onError = (err: Error) => {
|
|
118
|
+
stream.removeAllListeners();
|
|
119
|
+
|
|
120
|
+
if (!doneCalled) {
|
|
121
|
+
doneCalled = true;
|
|
122
|
+
|
|
123
|
+
// If the error is not an AbortError, reload the watch
|
|
124
|
+
if (err.name !== "AbortError") {
|
|
125
|
+
watchCfg.logFn?.(err, "stream error");
|
|
126
|
+
void reload(err);
|
|
127
|
+
} else {
|
|
128
|
+
watchCfg.logFn?.("watch aborted via WatchController.abort()");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const cleanup = () => {
|
|
134
|
+
if (!doneCalled) {
|
|
135
|
+
doneCalled = true;
|
|
136
|
+
stream.removeAllListeners();
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
// Make the actual request
|
|
142
|
+
const response = await fetch(url, { ...opts });
|
|
143
|
+
|
|
144
|
+
// If the request is successful, start listening for events
|
|
145
|
+
if (response.ok) {
|
|
146
|
+
const { body } = response;
|
|
147
|
+
|
|
148
|
+
// Reset the retry count
|
|
149
|
+
retryCount = 0;
|
|
150
|
+
|
|
151
|
+
stream.on("error", onError);
|
|
152
|
+
stream.on("close", cleanup);
|
|
153
|
+
stream.on("finish", cleanup);
|
|
154
|
+
|
|
155
|
+
// Listen for events and call the callback function
|
|
156
|
+
stream.on("data", line => {
|
|
157
|
+
try {
|
|
158
|
+
// Parse the event payload
|
|
159
|
+
const { object: payload, type: phase } = JSON.parse(line) as {
|
|
160
|
+
type: WatchPhase;
|
|
161
|
+
object: InstanceType<T>;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Call the callback function with the parsed payload
|
|
165
|
+
void callback(payload, phase as WatchPhase);
|
|
166
|
+
} catch (err) {
|
|
167
|
+
watchCfg.logFn?.(err, "watch callback error");
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
body.on("error", onError);
|
|
172
|
+
body.on("close", cleanup);
|
|
173
|
+
body.on("finish", cleanup);
|
|
174
|
+
|
|
175
|
+
// Pipe the response body to the stream
|
|
176
|
+
body.pipe(stream);
|
|
177
|
+
} else {
|
|
178
|
+
throw new Error(`watch failed: ${response.status} ${response.statusText}`);
|
|
179
|
+
}
|
|
180
|
+
} catch (e) {
|
|
181
|
+
onError(e);
|
|
44
182
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
terminal: false,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Listen for events and call the callback function
|
|
67
|
-
rl.on("line", line => {
|
|
68
|
-
try {
|
|
69
|
-
// Parse the event payload
|
|
70
|
-
const { object: payload, type: phase } = JSON.parse(line) as {
|
|
71
|
-
type: WatchPhase;
|
|
72
|
-
object: InstanceType<T>;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// Call the callback function with the parsed payload
|
|
76
|
-
void callback(payload, phase as WatchPhase);
|
|
77
|
-
} catch (ignore) {
|
|
78
|
-
// ignore parse errors
|
|
183
|
+
|
|
184
|
+
// On unhandled errors, retry the watch
|
|
185
|
+
async function reload(e: Error) {
|
|
186
|
+
// If there are more attempts, retry the watch
|
|
187
|
+
if (watchCfg.retryMax! > retryCount) {
|
|
188
|
+
retryCount++;
|
|
189
|
+
|
|
190
|
+
watchCfg.logFn?.(`retrying watch ${retryCount}/${watchCfg.retryMax}`);
|
|
191
|
+
|
|
192
|
+
// Sleep for the specified delay or 5 seconds
|
|
193
|
+
await new Promise(r => setTimeout(r, watchCfg.retryDelaySec! * 1000));
|
|
194
|
+
|
|
195
|
+
// Retry the watch after the delay
|
|
196
|
+
await runner();
|
|
197
|
+
} else {
|
|
198
|
+
// Otherwise, call the finally function if it exists
|
|
199
|
+
if (watchCfg.retryFail) {
|
|
200
|
+
watchCfg.retryFail(e);
|
|
79
201
|
}
|
|
80
|
-
}
|
|
81
|
-
} else {
|
|
82
|
-
// If the request fails, throw an error
|
|
83
|
-
const error = new Error(response.statusText) as Error & {
|
|
84
|
-
statusCode: number | undefined;
|
|
85
|
-
};
|
|
86
|
-
error.statusCode = response.status;
|
|
87
|
-
throw error;
|
|
202
|
+
}
|
|
88
203
|
}
|
|
89
|
-
} catch (e) {
|
|
90
|
-
close(e);
|
|
91
204
|
}
|
|
92
205
|
|
|
93
|
-
|
|
206
|
+
await runner();
|
|
207
|
+
|
|
208
|
+
return abortWrapper;
|
|
94
209
|
}
|
package/src/kinds.test.ts
CHANGED
|
@@ -8,6 +8,10 @@ import { RegisterKind } from "./kinds";
|
|
|
8
8
|
import { GroupVersionKind } from "./types";
|
|
9
9
|
|
|
10
10
|
const testCases = [
|
|
11
|
+
{
|
|
12
|
+
name: kind.Event,
|
|
13
|
+
expected: { group: "events.k8s.io", version: "v1", kind: "Event" },
|
|
14
|
+
},
|
|
11
15
|
{
|
|
12
16
|
name: kind.ClusterRole,
|
|
13
17
|
expected: { group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole" },
|
package/src/kinds.ts
CHANGED
|
@@ -4,6 +4,20 @@
|
|
|
4
4
|
import { GenericClass, GroupVersionKind } from "./types";
|
|
5
5
|
|
|
6
6
|
const gvkMap: Record<string, GroupVersionKind> = {
|
|
7
|
+
/**
|
|
8
|
+
* Represents a K8s Event resource.
|
|
9
|
+
* Event is a report of an event somewhere in the cluster. It generally denotes some state change in the system.
|
|
10
|
+
* Events have a limited retention time and triggers and messages may evolve with time. Event consumers should not
|
|
11
|
+
* rely on the timing of an event with a given Reason reflecting a consistent underlying trigger, or the continued
|
|
12
|
+
* existence of events with that Reason. Events should be treated as informative, best-effort, supplemental data.
|
|
13
|
+
* @see {@link https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/event-v1/}
|
|
14
|
+
*/
|
|
15
|
+
CoreV1Event: {
|
|
16
|
+
kind: "Event",
|
|
17
|
+
version: "v1",
|
|
18
|
+
group: "events.k8s.io",
|
|
19
|
+
},
|
|
20
|
+
|
|
7
21
|
/**
|
|
8
22
|
* Represents a K8s ClusterRole resource.
|
|
9
23
|
* ClusterRole is a set of permissions that can be bound to a user or group in a cluster-wide scope.
|
package/src/types.ts
CHANGED
|
@@ -33,3 +33,10 @@ export interface GroupVersionKind {
|
|
|
33
33
|
/** Optional, override the plural name for use in Webhook rules generation */
|
|
34
34
|
readonly plural?: string;
|
|
35
35
|
}
|
|
36
|
+
|
|
37
|
+
export interface LogFn {
|
|
38
|
+
/* tslint:disable:no-unnecessary-generics */
|
|
39
|
+
<T extends object>(obj: T, msg?: string, ...args: never[]): void;
|
|
40
|
+
(obj: unknown, msg?: string, ...args: never[]): void;
|
|
41
|
+
(msg: string, ...args: never[]): void;
|
|
42
|
+
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// __mocks__/@kubernetes/client-node.ts
|
|
2
|
-
|
|
3
|
-
import { jest } from "@jest/globals";
|
|
4
|
-
|
|
5
|
-
const actual = jest.requireActual("@kubernetes/client-node") as any;
|
|
6
|
-
|
|
7
|
-
const cloned = { ...actual };
|
|
8
|
-
|
|
9
|
-
cloned.KubeConfig = class MockedKubeConfig {
|
|
10
|
-
loadFromDefault = jest.fn();
|
|
11
|
-
|
|
12
|
-
applyToFetchOptions = jest.fn(data => data);
|
|
13
|
-
|
|
14
|
-
getCurrentCluster() {
|
|
15
|
-
return {
|
|
16
|
-
server: "http://jest-test:8080",
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// export all elements of the mocked module
|
|
22
|
-
module.exports = cloned;
|
package/commitlint.config.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = { extends: ["@commitlint/config-conventional"] };
|