kubernetes-fluent-client 3.1.2 → 3.2.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.
Files changed (61) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/.lintstagedrc.json +5 -0
  3. package/dist/fluent/watch.d.ts.map +1 -1
  4. package/dist/fluent/watch.js +4 -3
  5. package/dist/upstream.d.ts +1 -1
  6. package/dist/upstream.d.ts.map +1 -1
  7. package/dist/upstream.js +2 -1
  8. package/package.json +9 -6
  9. package/src/fluent/watch.ts +6 -4
  10. package/src/upstream.ts +1 -0
  11. package/dist/fetch.test.d.ts +0 -2
  12. package/dist/fetch.test.d.ts.map +0 -1
  13. package/dist/fetch.test.js +0 -97
  14. package/dist/fileSystem.test.d.ts +0 -2
  15. package/dist/fileSystem.test.d.ts.map +0 -1
  16. package/dist/fileSystem.test.js +0 -75
  17. package/dist/fluent/http2-watch.spec.d.ts +0 -2
  18. package/dist/fluent/http2-watch.spec.d.ts.map +0 -1
  19. package/dist/fluent/http2-watch.spec.js +0 -284
  20. package/dist/fluent/index.test.d.ts +0 -2
  21. package/dist/fluent/index.test.d.ts.map +0 -1
  22. package/dist/fluent/index.test.js +0 -193
  23. package/dist/fluent/utils.test.d.ts +0 -2
  24. package/dist/fluent/utils.test.d.ts.map +0 -1
  25. package/dist/fluent/utils.test.js +0 -215
  26. package/dist/fluent/watch.spec.d.ts +0 -2
  27. package/dist/fluent/watch.spec.d.ts.map +0 -1
  28. package/dist/fluent/watch.spec.js +0 -261
  29. package/dist/generate.test.d.ts +0 -2
  30. package/dist/generate.test.d.ts.map +0 -1
  31. package/dist/generate.test.js +0 -320
  32. package/dist/helpers.test.d.ts +0 -2
  33. package/dist/helpers.test.d.ts.map +0 -1
  34. package/dist/helpers.test.js +0 -37
  35. package/dist/kinds.test.d.ts +0 -2
  36. package/dist/kinds.test.d.ts.map +0 -1
  37. package/dist/kinds.test.js +0 -155
  38. package/dist/postProcessing.test.d.ts +0 -2
  39. package/dist/postProcessing.test.d.ts.map +0 -1
  40. package/dist/postProcessing.test.js +0 -550
  41. package/e2e/cli.e2e.test.ts +0 -127
  42. package/e2e/crds/policyreports.default.expected/policyreport-v1alpha1.ts +0 -332
  43. package/e2e/crds/policyreports.default.expected/policyreport-v1alpha2.ts +0 -360
  44. package/e2e/crds/policyreports.default.expected/policyreport-v1beta1.ts +0 -360
  45. package/e2e/crds/policyreports.no.post.expected/policyreport-v1alpha1.ts +0 -331
  46. package/e2e/crds/policyreports.no.post.expected/policyreport-v1alpha2.ts +0 -360
  47. package/e2e/crds/policyreports.no.post.expected/policyreport-v1beta1.ts +0 -360
  48. package/e2e/crds/test.yaml/policyreports.test.yaml +0 -1008
  49. package/e2e/crds/test.yaml/uds-podmonitors.test.yaml +0 -1245
  50. package/e2e/crds/uds-podmonitors.default.expected/podmonitor-v1.ts +0 -1333
  51. package/e2e/crds/uds-podmonitors.no.post.expected/podmonitor-v1.ts +0 -1360
  52. package/src/fetch.test.ts +0 -115
  53. package/src/fileSystem.test.ts +0 -67
  54. package/src/fluent/http2-watch.spec.ts +0 -335
  55. package/src/fluent/index.test.ts +0 -268
  56. package/src/fluent/utils.test.ts +0 -276
  57. package/src/fluent/watch.spec.ts +0 -299
  58. package/src/generate.test.ts +0 -399
  59. package/src/helpers.test.ts +0 -42
  60. package/src/kinds.test.ts +0 -166
  61. package/src/postProcessing.test.ts +0 -742
package/src/fetch.test.ts DELETED
@@ -1,115 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
3
-
4
- import { expect, test, beforeEach } from "@jest/globals";
5
-
6
- import { StatusCodes } from "http-status-codes";
7
- import nock from "nock";
8
- import { RequestInit } from "node-fetch";
9
- import { fetch } from "./fetch";
10
-
11
- beforeEach(() => {
12
- nock("https://jsonplaceholder.typicode.com")
13
- .get("/todos/1")
14
- .reply(200, {
15
- userId: 1,
16
- id: 1,
17
- title: "Example title",
18
- completed: false,
19
- })
20
- .post("/todos", {
21
- title: "test todo",
22
- userId: 1,
23
- completed: false,
24
- })
25
- .reply(200, (uri, requestBody) => requestBody)
26
- .get("/todos/empty-null")
27
- .reply(200, undefined)
28
- .get("/todos/empty-string")
29
- .reply(200, "")
30
- .get("/todos/empty-object")
31
- .reply(200, {})
32
- .get("/todos/invalid")
33
- .replyWithError("Something bad happened");
34
- });
35
-
36
- test("fetch: should return without type data", async () => {
37
- const url = "https://jsonplaceholder.typicode.com/todos/1";
38
- const { data, ok } = await fetch<{ title: string }>(url);
39
- expect(ok).toBe(true);
40
- expect(data["title"]).toBe("Example title");
41
- });
42
-
43
- test("fetch: should return parsed JSON response as a specific type", async () => {
44
- interface Todo {
45
- userId: number;
46
- id: number;
47
- title: string;
48
- completed: boolean;
49
- }
50
-
51
- const url = "https://jsonplaceholder.typicode.com/todos/1";
52
- const { data, ok } = await fetch<Todo>(url);
53
- expect(ok).toBe(true);
54
- expect(data.id).toBe(1);
55
- expect(typeof data.title).toBe("string");
56
- expect(typeof data.completed).toBe("boolean");
57
- });
58
-
59
- test("fetch: should handle additional request options", async () => {
60
- const url = "https://jsonplaceholder.typicode.com/todos";
61
- const requestOptions: RequestInit = {
62
- method: "POST",
63
- body: JSON.stringify({
64
- title: "test todo",
65
- userId: 1,
66
- completed: false,
67
- }),
68
- headers: {
69
- "Content-type": "application/json; charset=UTF-8",
70
- },
71
- };
72
-
73
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
- const { data, ok } = await fetch<any>(url, requestOptions);
75
- expect(ok).toBe(true);
76
- expect(data["title"]).toBe("test todo");
77
- expect(data["userId"]).toBe(1);
78
- expect(data["completed"]).toBe(false);
79
- });
80
-
81
- test("fetch: should handle empty (null) responses", async () => {
82
- const url = "https://jsonplaceholder.typicode.com/todos/empty-null";
83
- const resp = await fetch(url);
84
-
85
- expect(resp.data).toBe("");
86
- expect(resp.ok).toBe(true);
87
- expect(resp.status).toBe(StatusCodes.OK);
88
- });
89
-
90
- test("fetch: should handle empty (string) responses", async () => {
91
- const url = "https://jsonplaceholder.typicode.com/todos/empty-string";
92
- const resp = await fetch(url);
93
-
94
- expect(resp.data).toBe("");
95
- expect(resp.ok).toBe(true);
96
- expect(resp.status).toBe(StatusCodes.OK);
97
- });
98
-
99
- test("fetch: should handle empty (object) responses", async () => {
100
- const url = "https://jsonplaceholder.typicode.com/todos/empty-object";
101
- const resp = await fetch(url);
102
-
103
- expect(resp.data).toEqual({});
104
- expect(resp.ok).toBe(true);
105
- expect(resp.status).toBe(StatusCodes.OK);
106
- });
107
-
108
- test("fetch: should handle failed requests without throwing an error", async () => {
109
- const url = "https://jsonplaceholder.typicode.com/todos/invalid";
110
- const resp = await fetch(url);
111
-
112
- expect(resp.data).toBe(undefined);
113
- expect(resp.ok).toBe(false);
114
- expect(resp.status).toBe(StatusCodes.BAD_REQUEST);
115
- });
@@ -1,67 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
3
-
4
- import * as fs from "fs";
5
- import { NodeFileSystem } from "./fileSystem";
6
- import { beforeEach, describe, expect, jest, test } from "@jest/globals";
7
-
8
- // Mock the fs module
9
- jest.mock("fs");
10
-
11
- describe("NodeFileSystem", () => {
12
- let nodeFileSystem: NodeFileSystem;
13
-
14
- beforeEach(() => {
15
- nodeFileSystem = new NodeFileSystem();
16
- jest.clearAllMocks(); // Clear all mocks before each test
17
- });
18
-
19
- describe("readFile", () => {
20
- test("should call fs.readFileSync with correct arguments", () => {
21
- const mockFilePath = "test-file.txt";
22
- const mockFileContent = "This is a test file";
23
-
24
- // Mock the fs.readFileSync method to return the mock file content
25
- (fs.readFileSync as jest.Mock).mockReturnValue(mockFileContent);
26
-
27
- const result = nodeFileSystem.readFile(mockFilePath);
28
-
29
- // Assert that fs.readFileSync was called with the correct file path and encoding
30
- expect(fs.readFileSync).toHaveBeenCalledWith(mockFilePath, "utf8");
31
-
32
- // Assert that the returned content matches the mock file content
33
- expect(result).toBe(mockFileContent);
34
- });
35
- });
36
-
37
- describe("writeFile", () => {
38
- test("should call fs.writeFileSync with correct arguments", () => {
39
- const mockFilePath = "test-file.txt";
40
- const mockFileContent = "This is a test file";
41
-
42
- // Call the writeFile method
43
- nodeFileSystem.writeFile(mockFilePath, mockFileContent);
44
-
45
- // Assert that fs.writeFileSync was called with the correct arguments
46
- expect(fs.writeFileSync).toHaveBeenCalledWith(mockFilePath, mockFileContent, "utf8");
47
- });
48
- });
49
-
50
- describe("readdirSync", () => {
51
- test("should call fs.readdirSync with correct arguments and return file list", () => {
52
- const mockDirectoryPath = "test-directory";
53
- const mockFileList = ["file1.txt", "file2.txt"];
54
-
55
- // Mock the fs.readdirSync method to return the mock file list
56
- (fs.readdirSync as jest.Mock).mockReturnValue(mockFileList);
57
-
58
- const result = nodeFileSystem.readdirSync(mockDirectoryPath);
59
-
60
- // Assert that fs.readdirSync was called with the correct directory path
61
- expect(fs.readdirSync).toHaveBeenCalledWith(mockDirectoryPath);
62
-
63
- // Assert that the returned file list matches the mock file list
64
- expect(result).toEqual(mockFileList);
65
- });
66
- });
67
- });
@@ -1,335 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { afterEach, beforeEach, describe, expect, it, jest } from "@jest/globals";
3
- import http2 from "http2";
4
- import { Watcher } from "./watch";
5
- import { WatchEvent, kind } from "..";
6
- import { WatchPhase } from "./types";
7
- import { K8s } from ".";
8
-
9
- jest.mock("http2");
10
-
11
- describe("Watcher HTTP2", () => {
12
- let watcher: Watcher<typeof kind.Pod>;
13
- let mockClient: jest.Mocked<http2.ClientHttp2Session>;
14
- let mockReq: jest.Mocked<http2.ClientHttp2Stream>;
15
- const evtMock = jest.fn<(update: kind.Pod, phase: WatchPhase) => void>();
16
- const errMock = jest.fn<(err: Error) => void>();
17
-
18
- const setupAndStartWatcher = (eventType: WatchEvent, handler: (...args: any[]) => void) => {
19
- watcher.events.on(eventType, handler);
20
- watcher.start().catch(errMock);
21
- };
22
-
23
- beforeEach(() => {
24
- jest.clearAllMocks();
25
-
26
- // http2.client
27
- mockClient = {
28
- request: jest.fn(),
29
- close: jest.fn(),
30
- on: jest.fn(),
31
- destroy: jest.fn(),
32
- } as unknown as jest.Mocked<http2.ClientHttp2Session>;
33
-
34
- // http2.request stream
35
- mockReq = {
36
- on: jest.fn(),
37
- end: jest.fn(),
38
- setEncoding: jest.fn(),
39
- } as unknown as jest.Mocked<http2.ClientHttp2Stream>;
40
-
41
- // http2.connect function to return the mocked client session
42
- (http2.connect as jest.Mock).mockReturnValue(mockClient);
43
- });
44
-
45
- afterEach(() => {
46
- watcher.close();
47
- });
48
-
49
- it("should watch named resources", done => {
50
- const pod = createMockPod("pod-1", "1");
51
- const response = { type: "ADDED", object: pod };
52
-
53
- watcher = K8s(kind.Pod).Watch(evtMock, {
54
- useHTTP2: true,
55
- });
56
-
57
- mockReq.on.mockImplementation((event, callback) => {
58
- switch (event) {
59
- case "response":
60
- callback(
61
- { ":status": 200 } as http2.IncomingHttpHeaders & http2.IncomingHttpStatusHeader,
62
- 0,
63
- );
64
- break;
65
- case "data":
66
- setTimeout(() => {
67
- (callback as (chunk: Buffer) => void)(Buffer.from(JSON.stringify(response)));
68
- }, 10);
69
- break;
70
- case "end":
71
- setTimeout(() => {
72
- (callback as () => void)();
73
- done();
74
- }, 20);
75
- break;
76
- case "error":
77
- errMock(new Error("HTTP2 connection error"));
78
- break;
79
- }
80
- return mockReq;
81
- });
82
-
83
- mockClient.request.mockReturnValue(mockReq);
84
-
85
- setupAndStartWatcher(WatchEvent.CONNECT, () => {
86
- setupAndStartWatcher(WatchEvent.DATA, (receivedPod, phase) => {
87
- expect(receivedPod.metadata?.name).toBe("pod-1");
88
- expect(receivedPod.metadata?.resourceVersion).toBe("1");
89
- expect(phase).toBe(WatchPhase.Added);
90
- done();
91
- });
92
- });
93
- });
94
-
95
- it("should handle resource version is too old", done => {
96
- const errorResponse = {
97
- type: "ERROR",
98
- object: {
99
- kind: "Status",
100
- apiVersion: "v1",
101
- metadata: {},
102
- status: "Failure",
103
- message: "too old resource version: 123 (391079)",
104
- reason: "Gone",
105
- code: 410,
106
- },
107
- };
108
-
109
- watcher = K8s(kind.Pod).Watch(evtMock, {
110
- useHTTP2: true,
111
- });
112
-
113
- mockReq.on.mockImplementation((event, callback) => {
114
- switch (event) {
115
- case "response":
116
- callback(
117
- { ":status": 200 } as http2.IncomingHttpHeaders & http2.IncomingHttpStatusHeader,
118
- 0,
119
- );
120
- break;
121
- case "data":
122
- setTimeout(() => {
123
- (callback as (chunk: Buffer) => void)(Buffer.from(JSON.stringify(errorResponse)));
124
- }, 10);
125
- break;
126
- case "end":
127
- setTimeout(() => {
128
- (callback as () => void)();
129
- done();
130
- }, 20);
131
- break;
132
- case "error":
133
- errMock(new Error("HTTP2 connection error"));
134
- break;
135
- }
136
- return mockReq;
137
- });
138
-
139
- mockClient.request.mockReturnValue(mockReq);
140
-
141
- setupAndStartWatcher(WatchEvent.OLD_RESOURCE_VERSION, res => {
142
- expect(res).toEqual("123");
143
- done();
144
- });
145
- });
146
-
147
- it("should call the event handler for each event", done => {
148
- const pod = createMockPod("pod-0", "1");
149
- const response = { type: "ADDED", object: pod };
150
-
151
- watcher = K8s(kind.Pod).Watch(
152
- (evt, phase) => {
153
- expect(evt.metadata?.name).toEqual("pod-0");
154
- expect(phase).toEqual(WatchPhase.Added);
155
- },
156
- { useHTTP2: true },
157
- );
158
-
159
- mockReq.on.mockImplementation((event, callback) => {
160
- switch (event) {
161
- case "response":
162
- callback(
163
- { ":status": 200 } as http2.IncomingHttpHeaders & http2.IncomingHttpStatusHeader,
164
- 0,
165
- );
166
- break;
167
- case "data":
168
- setTimeout(() => {
169
- (callback as (chunk: Buffer) => void)(Buffer.from(JSON.stringify(response)));
170
- }, 10);
171
- break;
172
- case "end":
173
- setTimeout(() => {
174
- (callback as () => void)();
175
- }, 20);
176
- break;
177
- case "error":
178
- errMock(new Error("HTTP2 connection error"));
179
- break;
180
- }
181
- return mockReq;
182
- });
183
-
184
- mockClient.request.mockReturnValue(mockReq);
185
-
186
- watcher.start().catch(errMock);
187
- done();
188
- });
189
-
190
- it("should return the cache id", () => {
191
- watcher = K8s(kind.Pod).Watch(evtMock, {
192
- resyncDelaySec: 1,
193
- useHTTP2: true,
194
- });
195
- expect(watcher.getCacheID()).toEqual("d69b75a611");
196
- });
197
-
198
- it("should handle the CONNECT event", done => {
199
- watcher = K8s(kind.Pod).Watch(evtMock, {
200
- resyncDelaySec: 1,
201
- useHTTP2: true,
202
- });
203
- setupAndStartWatcher(WatchEvent.CONNECT, () => {});
204
- done();
205
- });
206
-
207
- it("should handle the DATA event", done => {
208
- watcher = K8s(kind.Pod).Watch(evtMock, {
209
- resyncDelaySec: 1,
210
- useHTTP2: true,
211
- });
212
- setupAndStartWatcher(WatchEvent.DATA, (pod, phase) => {
213
- expect(pod.metadata?.name).toEqual("pod-0");
214
- expect(phase).toEqual(WatchPhase.Added);
215
- });
216
- done();
217
- });
218
-
219
- it("should handle the NETWORK_ERROR event", done => {
220
- const errorMessage = "Something bad happened";
221
- watcher = K8s(kind.Pod).Watch(evtMock, {
222
- useHTTP2: true,
223
- resyncDelaySec: 1,
224
- });
225
-
226
- mockReq.on.mockImplementation((event, callback) => {
227
- if (event === "response") {
228
- callback(
229
- { ":status": 200 } as http2.IncomingHttpHeaders & http2.IncomingHttpStatusHeader,
230
- 0,
231
- );
232
- } else if (event === "error") {
233
- (callback as (err: Error) => void)(new Error(errorMessage));
234
- }
235
- return mockReq;
236
- });
237
-
238
- mockClient.request.mockReturnValue(mockReq);
239
-
240
- setupAndStartWatcher(WatchEvent.NETWORK_ERROR, error => {
241
- expect(error.message).toEqual(errorMessage);
242
- });
243
-
244
- watcher.start().catch(errMock);
245
- done();
246
- });
247
-
248
- it("should handle the RECONNECT event on an error", done => {
249
- const errorMessage = "Something bad happened";
250
-
251
- watcher = K8s(kind.Pod).Watch(evtMock, {
252
- useHTTP2: true,
253
- resyncDelaySec: 0.01,
254
- });
255
-
256
- let reconnectCount = 0;
257
-
258
- mockReq.on.mockImplementation((event, callback) => {
259
- if (event === "response") {
260
- callback(
261
- { ":status": 200 } as http2.IncomingHttpHeaders & http2.IncomingHttpStatusHeader,
262
- 0,
263
- );
264
- } else if (event === "error") {
265
- reconnectCount += 1;
266
- (callback as (err: Error) => void)(new Error(errorMessage));
267
- }
268
- return mockReq;
269
- });
270
-
271
- mockClient.request.mockReturnValue(mockReq);
272
-
273
- setupAndStartWatcher(WatchEvent.RECONNECT, count => {
274
- expect(count).toEqual(reconnectCount);
275
- });
276
-
277
- watcher.start().catch(errMock);
278
- done();
279
- });
280
- it("should perform a resync after the resync interval", done => {
281
- watcher = K8s(kind.Pod).Watch(evtMock, {
282
- useHTTP2: true,
283
- resyncDelaySec: 1,
284
- });
285
- watcher.start().catch(errMock);
286
- done();
287
- });
288
- it("should handle the GIVE_UP event", done => {
289
- watcher = K8s(kind.Pod).Watch(evtMock, {
290
- useHTTP2: true,
291
- lastSeenLimitSeconds: 0.01,
292
- resyncDelaySec: 0.01,
293
- resyncFailureMax: 1,
294
- });
295
- setupAndStartWatcher(WatchEvent.GIVE_UP, () => {
296
- expect(errMock).toBeCalled();
297
- });
298
- watcher.start().catch(errMock);
299
- done();
300
- });
301
- });
302
-
303
- /**
304
- * Creates a mock pod object
305
- *
306
- * @param name The name of the pod
307
- * @param resourceVersion The resource version of the pod
308
- * @returns A mock pod object
309
- */
310
- function createMockPod(name: string, resourceVersion: string): kind.Pod {
311
- return {
312
- kind: "Pod",
313
- apiVersion: "v1",
314
- metadata: {
315
- name,
316
- resourceVersion,
317
- uid: "abc-123-xyz",
318
- },
319
- spec: {
320
- containers: [
321
- {
322
- name: "nginx",
323
- image: "nginx:1.14.2",
324
- ports: [
325
- {
326
- containerPort: 80,
327
- protocol: "TCP",
328
- },
329
- ],
330
- },
331
- ],
332
- },
333
- status: {},
334
- };
335
- }