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