kubernetes-fluent-client 3.1.1 → 3.1.3

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 (60) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/.lintstagedrc.json +5 -0
  3. package/dist/fluent/types.d.ts +14 -0
  4. package/dist/fluent/types.d.ts.map +1 -1
  5. package/dist/fluent/watch.d.ts.map +1 -1
  6. package/dist/fluent/watch.js +121 -71
  7. package/package.json +8 -5
  8. package/src/fluent/types.ts +16 -0
  9. package/src/fluent/watch.ts +136 -81
  10. package/dist/fetch.test.d.ts +0 -2
  11. package/dist/fetch.test.d.ts.map +0 -1
  12. package/dist/fetch.test.js +0 -97
  13. package/dist/fileSystem.test.d.ts +0 -2
  14. package/dist/fileSystem.test.d.ts.map +0 -1
  15. package/dist/fileSystem.test.js +0 -75
  16. package/dist/fluent/http2-watch.spec.d.ts +0 -2
  17. package/dist/fluent/http2-watch.spec.d.ts.map +0 -1
  18. package/dist/fluent/http2-watch.spec.js +0 -284
  19. package/dist/fluent/index.test.d.ts +0 -2
  20. package/dist/fluent/index.test.d.ts.map +0 -1
  21. package/dist/fluent/index.test.js +0 -193
  22. package/dist/fluent/utils.test.d.ts +0 -2
  23. package/dist/fluent/utils.test.d.ts.map +0 -1
  24. package/dist/fluent/utils.test.js +0 -215
  25. package/dist/fluent/watch.spec.d.ts +0 -2
  26. package/dist/fluent/watch.spec.d.ts.map +0 -1
  27. package/dist/fluent/watch.spec.js +0 -261
  28. package/dist/generate.test.d.ts +0 -2
  29. package/dist/generate.test.d.ts.map +0 -1
  30. package/dist/generate.test.js +0 -320
  31. package/dist/helpers.test.d.ts +0 -2
  32. package/dist/helpers.test.d.ts.map +0 -1
  33. package/dist/helpers.test.js +0 -37
  34. package/dist/kinds.test.d.ts +0 -2
  35. package/dist/kinds.test.d.ts.map +0 -1
  36. package/dist/kinds.test.js +0 -155
  37. package/dist/postProcessing.test.d.ts +0 -2
  38. package/dist/postProcessing.test.d.ts.map +0 -1
  39. package/dist/postProcessing.test.js +0 -550
  40. package/e2e/cli.e2e.test.ts +0 -127
  41. package/e2e/crds/policyreports.default.expected/policyreport-v1alpha1.ts +0 -332
  42. package/e2e/crds/policyreports.default.expected/policyreport-v1alpha2.ts +0 -360
  43. package/e2e/crds/policyreports.default.expected/policyreport-v1beta1.ts +0 -360
  44. package/e2e/crds/policyreports.no.post.expected/policyreport-v1alpha1.ts +0 -331
  45. package/e2e/crds/policyreports.no.post.expected/policyreport-v1alpha2.ts +0 -360
  46. package/e2e/crds/policyreports.no.post.expected/policyreport-v1beta1.ts +0 -360
  47. package/e2e/crds/test.yaml/policyreports.test.yaml +0 -1008
  48. package/e2e/crds/test.yaml/uds-podmonitors.test.yaml +0 -1245
  49. package/e2e/crds/uds-podmonitors.default.expected/podmonitor-v1.ts +0 -1333
  50. package/e2e/crds/uds-podmonitors.no.post.expected/podmonitor-v1.ts +0 -1360
  51. package/src/fetch.test.ts +0 -115
  52. package/src/fileSystem.test.ts +0 -67
  53. package/src/fluent/http2-watch.spec.ts +0 -335
  54. package/src/fluent/index.test.ts +0 -268
  55. package/src/fluent/utils.test.ts +0 -276
  56. package/src/fluent/watch.spec.ts +0 -299
  57. package/src/generate.test.ts +0 -399
  58. package/src/helpers.test.ts +0 -42
  59. package/src/kinds.test.ts +0 -166
  60. package/src/postProcessing.test.ts +0 -742
@@ -1,268 +0,0 @@
1
- import { beforeEach, describe, expect, it, jest } from "@jest/globals";
2
- import { V1APIGroup } from "@kubernetes/client-node";
3
- import { Operation } from "fast-json-patch";
4
-
5
- import { K8s } from ".";
6
- import { fetch } from "../fetch";
7
- import { Pod } from "../upstream";
8
- import { k8sCfg, k8sExec } from "./utils";
9
-
10
- // Setup mocks
11
- jest.mock("./utils");
12
- jest.mock("../fetch");
13
-
14
- const generateFakePodManagedFields = (manager: string) => {
15
- return [
16
- {
17
- apiVersion: "v1",
18
- fieldsType: "FieldsV1",
19
- fieldsV1: {
20
- "f:metadata": {
21
- "f:labels": {
22
- "f:fake": {},
23
- },
24
- "f:spec": {
25
- "f:containers": {
26
- 'k:{"name":"fake"}': {
27
- "f:image": {},
28
- "f:name": {},
29
- "f:resources": {
30
- "f:limits": {
31
- "f:cpu": {},
32
- "f:memory": {},
33
- },
34
- "f:requests": {
35
- "f:cpu": {},
36
- "f:memory": {},
37
- },
38
- },
39
- },
40
- },
41
- },
42
- },
43
- },
44
- manager: manager,
45
- operation: "Apply",
46
- },
47
- ];
48
- };
49
- describe("Kube", () => {
50
- const fakeResource = {
51
- metadata: {
52
- name: "fake",
53
- namespace: "default",
54
- managedFields: generateFakePodManagedFields("pepr"),
55
- },
56
- };
57
-
58
- const mockedKubeCfg = jest.mocked(k8sCfg);
59
- const mockedKubeExec = jest.mocked(k8sExec).mockResolvedValue(fakeResource);
60
-
61
- beforeEach(() => {
62
- // Clear all instances and calls to constructor and all methods:
63
- mockedKubeExec.mockClear();
64
- });
65
-
66
- it("should create a resource", async () => {
67
- const result = await K8s(Pod).Create(fakeResource);
68
-
69
- expect(result).toEqual(fakeResource);
70
- expect(mockedKubeExec).toHaveBeenCalledWith(
71
- Pod,
72
- expect.objectContaining({
73
- name: "fake",
74
- namespace: "default",
75
- }),
76
- "POST",
77
- fakeResource,
78
- );
79
- });
80
-
81
- it("should delete a resource", async () => {
82
- await K8s(Pod).Delete(fakeResource);
83
-
84
- expect(mockedKubeExec).toHaveBeenCalledWith(
85
- Pod,
86
- expect.objectContaining({
87
- name: "fake",
88
- namespace: "default",
89
- }),
90
- "DELETE",
91
- );
92
- });
93
-
94
- it("should patch a resource", async () => {
95
- const patchOperations: Operation[] = [
96
- { op: "replace", path: "/metadata/name", value: "new-fake" },
97
- ];
98
-
99
- const result = await K8s(Pod).Patch(patchOperations);
100
-
101
- expect(result).toEqual(fakeResource);
102
- expect(mockedKubeExec).toHaveBeenCalledWith(Pod, {}, "PATCH", patchOperations);
103
- });
104
-
105
- it("should patch the status of a resource", async () => {
106
- await K8s(Pod).PatchStatus({
107
- metadata: {
108
- name: "fake",
109
- namespace: "default",
110
- managedFields: generateFakePodManagedFields("pepr"),
111
- },
112
- spec: { priority: 3 },
113
- status: {
114
- phase: "Ready",
115
- },
116
- });
117
-
118
- expect(k8sExec).toBeCalledWith(
119
- Pod,
120
- expect.objectContaining({
121
- name: "fake",
122
- namespace: "default",
123
- }),
124
- "PATCH_STATUS",
125
- {
126
- apiVersion: "v1",
127
- kind: "Pod",
128
- metadata: {
129
- name: "fake",
130
- namespace: "default",
131
- managedFields: generateFakePodManagedFields("pepr"),
132
- },
133
- spec: { priority: 3 },
134
- status: {
135
- phase: "Ready",
136
- },
137
- },
138
- );
139
- });
140
-
141
- it("should filter with WithField", async () => {
142
- await K8s(Pod).WithField("metadata.name", "fake").Get();
143
-
144
- expect(mockedKubeExec).toHaveBeenCalledWith(
145
- Pod,
146
- expect.objectContaining({
147
- fields: {
148
- "metadata.name": "fake",
149
- },
150
- }),
151
- "GET",
152
- );
153
- });
154
-
155
- it("should filter with WithLabel", async () => {
156
- await K8s(Pod).WithLabel("app", "fakeApp").Get();
157
-
158
- expect(mockedKubeExec).toHaveBeenCalledWith(
159
- Pod,
160
- expect.objectContaining({
161
- labels: {
162
- app: "fakeApp",
163
- },
164
- }),
165
- "GET",
166
- );
167
- });
168
-
169
- it("should use InNamespace", async () => {
170
- await K8s(Pod).InNamespace("fakeNamespace").Get();
171
-
172
- expect(mockedKubeExec).toHaveBeenCalledWith(
173
- Pod,
174
- expect.objectContaining({
175
- namespace: "fakeNamespace",
176
- }),
177
- "GET",
178
- );
179
- });
180
-
181
- it("should throw an error if namespace is already specified", async () => {
182
- expect(() => K8s(Pod, { namespace: "default" }).InNamespace("fakeNamespace")).toThrow(
183
- "Namespace already specified: default",
184
- );
185
- });
186
-
187
- it("should handle Delete when the resource doesn't exist", async () => {
188
- mockedKubeExec.mockRejectedValueOnce({ status: 404 }); // Not Found on first call
189
- await expect(K8s(Pod).Delete("fakeResource")).resolves.toBeUndefined();
190
- });
191
-
192
- it("should handle Get", async () => {
193
- const result = await K8s(Pod).Get("fakeResource");
194
-
195
- expect(result).toEqual(fakeResource);
196
- expect(mockedKubeExec).toHaveBeenCalledWith(
197
- Pod,
198
- expect.objectContaining({
199
- name: "fakeResource",
200
- }),
201
- "GET",
202
- );
203
- });
204
-
205
- it("should thrown an error if Get is called with a name and filters are already specified a name", async () => {
206
- await expect(K8s(Pod, { name: "fake" }).Get("fakeResource")).rejects.toThrow(
207
- "Name already specified: fake",
208
- );
209
- });
210
-
211
- it("should throw an error if no patch operations provided", async () => {
212
- await expect(K8s(Pod).Patch([])).rejects.toThrow("No operations specified");
213
- });
214
-
215
- it("should allow Apply of deep partials", async () => {
216
- const result = await K8s(Pod).Apply({ metadata: { name: "fake" }, spec: { priority: 3 } });
217
- expect(result).toEqual(fakeResource);
218
- });
219
-
220
- it("should allow force apply to resolve FieldManagerConflict", async () => {
221
- const result = await K8s(Pod).Apply(
222
- {
223
- metadata: { name: "fake", managedFields: generateFakePodManagedFields("kubectl") },
224
- spec: { priority: 3 },
225
- },
226
- { force: true },
227
- );
228
- expect(result).toEqual(fakeResource);
229
- });
230
-
231
- it("should throw an error if a Delete failed for a reason other than Not Found", async () => {
232
- mockedKubeExec.mockRejectedValueOnce({ status: 500 }); // Internal Server Error on first call
233
- await expect(K8s(Pod).Delete("fakeResource")).rejects.toEqual(
234
- expect.objectContaining({ status: 500 }),
235
- );
236
- });
237
-
238
- it("should create a raw api request", async () => {
239
- mockedKubeCfg.mockReturnValue(
240
- new Promise(r =>
241
- r({
242
- serverUrl: "http://localhost:8080",
243
- opts: {},
244
- }),
245
- ),
246
- );
247
- const mockResp = {
248
- kind: "APIVersions",
249
- versions: ["v1"],
250
- serverAddressByClientCIDRs: [
251
- {
252
- serverAddress: "172.27.0.3:6443",
253
- },
254
- ],
255
- };
256
-
257
- jest.mocked(fetch).mockResolvedValue({
258
- ok: true,
259
- data: mockResp,
260
- status: 200,
261
- statusText: "OK",
262
- });
263
-
264
- const result = await K8s(V1APIGroup).Raw("/api");
265
-
266
- expect(result).toEqual(mockResp);
267
- });
268
- });
@@ -1,276 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
3
-
4
- import { beforeEach, describe, expect, it, jest } from "@jest/globals";
5
- import { Headers } from "node-fetch";
6
-
7
- import { fetch } from "../fetch";
8
- import { RegisterKind } from "../kinds";
9
- import { GenericClass } from "../types";
10
- import { ClusterRole, Ingress, Pod } from "../upstream";
11
- import { Filters } from "./types";
12
- import { k8sExec, pathBuilder } from "./utils";
13
-
14
- jest.mock("https");
15
- jest.mock("../fetch");
16
-
17
- describe("pathBuilder Function", () => {
18
- const serverUrl = "https://jest-test:8080";
19
- it("should throw an error if the kind is not specified and the model is not a KubernetesObject", () => {
20
- const model = { name: "Unknown" } as unknown as GenericClass;
21
- const filters: Filters = {};
22
- expect(() => pathBuilder("", model, filters)).toThrow("Kind not specified for Unknown");
23
- });
24
-
25
- it("should generate a path with a set-based label selector", () => {
26
- const filters: Filters = {
27
- namespace: "default",
28
- name: "mypod",
29
- labels: { iamalabel: "" },
30
- };
31
- const result = pathBuilder(serverUrl, Pod, filters);
32
- const expected = new URL(
33
- "/api/v1/namespaces/default/pods/mypod?labelSelector=iamalabel",
34
- serverUrl,
35
- );
36
-
37
- expect(result.toString()).toEqual(expected.toString());
38
- });
39
-
40
- it("should generate a path for core group kinds (with custom filters)", () => {
41
- const filters: Filters = {
42
- namespace: "default",
43
- name: "mypod",
44
- fields: { iamafield: "iamavalue" },
45
- labels: { iamalabel: "iamalabelvalue" },
46
- };
47
- const result = pathBuilder(serverUrl, Pod, filters);
48
- const expected = new URL(
49
- "/api/v1/namespaces/default/pods/mypod?fieldSelector=iamafield%3Diamavalue&labelSelector=iamalabel%3Diamalabelvalue",
50
- serverUrl,
51
- );
52
-
53
- expect(result.toString()).toEqual(expected.toString());
54
- });
55
-
56
- it("Version not specified in a Kind", () => {
57
- const filters: Filters = {
58
- namespace: "default",
59
- name: "mypod",
60
- };
61
- class Fake {
62
- name: string;
63
- constructor() {
64
- this.name = "Fake";
65
- }
66
- }
67
- RegisterKind(Fake, {
68
- kind: "Fake",
69
- version: "",
70
- group: "fake",
71
- });
72
- try {
73
- pathBuilder(serverUrl, Fake, filters);
74
- } catch (e) {
75
- expect(e.message).toEqual(`Version not specified for Fake`);
76
- }
77
- });
78
-
79
- it("should generate a path for core group kinds", () => {
80
- const filters: Filters = { namespace: "default", name: "mypod" };
81
- const result = pathBuilder(serverUrl, Pod, filters);
82
- const expected = new URL("/api/v1/namespaces/default/pods/mypod", serverUrl);
83
- expect(result).toEqual(expected);
84
- });
85
-
86
- it("should generate a path for non-core group kinds", () => {
87
- const filters: Filters = {
88
- namespace: "default",
89
- name: "myingress",
90
- };
91
- const result = pathBuilder(serverUrl, Ingress, filters);
92
- const expected = new URL(
93
- "/apis/networking.k8s.io/v1/namespaces/default/ingresses/myingress",
94
- serverUrl,
95
- );
96
- expect(result).toEqual(expected);
97
- });
98
-
99
- it("should generate a path without a namespace if not provided", () => {
100
- const filters: Filters = { name: "tester" };
101
- const result = pathBuilder(serverUrl, ClusterRole, filters);
102
- const expected = new URL("/apis/rbac.authorization.k8s.io/v1/clusterroles/tester", serverUrl);
103
- expect(result).toEqual(expected);
104
- });
105
-
106
- it("should generate a path without a name if excludeName is true", () => {
107
- const filters: Filters = { namespace: "default", name: "mypod" };
108
- const result = pathBuilder(serverUrl, Pod, filters, true);
109
- const expected = new URL("/api/v1/namespaces/default/pods", serverUrl);
110
- expect(result).toEqual(expected);
111
- });
112
- });
113
-
114
- describe("kubeExec Function", () => {
115
- const mockedFetch = jest.mocked(fetch);
116
-
117
- const fakeFilters: Filters = { name: "fake", namespace: "default" };
118
- const fakeMethod = "GET";
119
- const fakePayload = {
120
- metadata: { name: "fake", namespace: "default" },
121
- status: { phase: "Ready" },
122
- };
123
- const fakeUrl = new URL("http://jest-test:8080/api/v1/namespaces/default/pods/fake");
124
- const fakeOpts = {
125
- body: JSON.stringify(fakePayload),
126
- compress: true,
127
- headers: new Headers({
128
- "Content-Type": "application/json",
129
- "User-Agent": `kubernetes-fluent-client`,
130
- }),
131
- method: fakeMethod,
132
- };
133
-
134
- beforeEach(() => {
135
- mockedFetch.mockClear();
136
- });
137
-
138
- it("should make a successful fetch call", async () => {
139
- mockedFetch.mockResolvedValueOnce({
140
- ok: true,
141
- data: fakePayload,
142
- status: 200,
143
- statusText: "OK",
144
- });
145
-
146
- const result = await k8sExec(Pod, fakeFilters, fakeMethod, fakePayload);
147
-
148
- expect(result).toEqual(fakePayload);
149
- expect(mockedFetch).toHaveBeenCalledWith(fakeUrl, expect.objectContaining(fakeOpts));
150
- });
151
-
152
- it("should handle PATCH_STATUS", async () => {
153
- mockedFetch.mockResolvedValueOnce({
154
- ok: true,
155
- data: fakePayload,
156
- status: 200,
157
- statusText: "OK",
158
- });
159
-
160
- const result = await k8sExec(Pod, fakeFilters, "PATCH_STATUS", fakePayload);
161
-
162
- expect(result).toEqual(fakePayload);
163
- expect(mockedFetch).toHaveBeenCalledWith(
164
- new URL("http://jest-test:8080/api/v1/namespaces/default/pods/fake/status"),
165
- expect.objectContaining({
166
- method: "PATCH",
167
- compress: true,
168
- headers: new Headers({
169
- "Content-Type": "application/merge-patch+json",
170
- "User-Agent": `kubernetes-fluent-client`,
171
- }),
172
- body: JSON.stringify({ status: fakePayload.status }),
173
- }),
174
- );
175
- });
176
-
177
- it("should handle PATCH", async () => {
178
- mockedFetch.mockResolvedValueOnce({
179
- ok: true,
180
- data: fakePayload,
181
- status: 200,
182
- statusText: "OK",
183
- });
184
-
185
- const patchPayload = [{ op: "replace", path: "/status/phase", value: "Ready" }];
186
-
187
- const result = await k8sExec(Pod, fakeFilters, "PATCH", patchPayload);
188
-
189
- expect(result).toEqual(fakePayload);
190
- expect(mockedFetch).toHaveBeenCalledWith(
191
- new URL("http://jest-test:8080/api/v1/namespaces/default/pods/fake"),
192
- expect.objectContaining({
193
- method: "PATCH",
194
- compress: true,
195
- headers: new Headers({
196
- "Content-Type": "application/json-patch+json",
197
- "User-Agent": `kubernetes-fluent-client`,
198
- }),
199
- body: JSON.stringify(patchPayload),
200
- }),
201
- );
202
- });
203
-
204
- it("should handle APPLY", async () => {
205
- mockedFetch.mockResolvedValueOnce({
206
- ok: true,
207
- data: fakePayload,
208
- status: 200,
209
- statusText: "OK",
210
- });
211
-
212
- const result = await k8sExec(Pod, fakeFilters, "APPLY", fakePayload);
213
-
214
- expect(result).toEqual(fakePayload);
215
- expect(mockedFetch).toHaveBeenCalledWith(
216
- new URL(
217
- "http://jest-test:8080/api/v1/namespaces/default/pods/fake?fieldManager=pepr&fieldValidation=Strict&force=false",
218
- ),
219
- expect.objectContaining({
220
- method: "PATCH",
221
- compress: true,
222
- headers: new Headers({
223
- "Content-Type": "application/apply-patch+yaml",
224
- "User-Agent": `kubernetes-fluent-client`,
225
- }),
226
- body: JSON.stringify(fakePayload),
227
- }),
228
- );
229
- });
230
-
231
- it("should handle APPLY with force", async () => {
232
- mockedFetch.mockResolvedValueOnce({
233
- ok: true,
234
- data: fakePayload,
235
- status: 200,
236
- statusText: "OK",
237
- });
238
-
239
- const result = await k8sExec(Pod, fakeFilters, "APPLY", fakePayload, { force: true });
240
-
241
- expect(result).toEqual(fakePayload);
242
- expect(mockedFetch).toHaveBeenCalledWith(
243
- new URL(
244
- "http://jest-test:8080/api/v1/namespaces/default/pods/fake?fieldManager=pepr&fieldValidation=Strict&force=true",
245
- ),
246
- expect.objectContaining({
247
- method: "PATCH",
248
- compress: true,
249
- headers: new Headers({
250
- "Content-Type": "application/apply-patch+yaml",
251
- "User-Agent": `kubernetes-fluent-client`,
252
- }),
253
- body: JSON.stringify(fakePayload),
254
- }),
255
- );
256
- });
257
-
258
- it("should handle fetch call failure", async () => {
259
- const fakeStatus = 404;
260
- const fakeStatusText = "Not Found";
261
-
262
- mockedFetch.mockResolvedValueOnce({
263
- ok: false,
264
- data: null,
265
- status: fakeStatus,
266
- statusText: fakeStatusText,
267
- });
268
-
269
- await expect(k8sExec(Pod, fakeFilters, fakeMethod, fakePayload)).rejects.toEqual(
270
- expect.objectContaining({
271
- status: fakeStatus,
272
- statusText: fakeStatusText,
273
- }),
274
- );
275
- });
276
- });