kubernetes-fluent-client 3.1.0 → 3.1.2
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/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +68 -0
- package/dist/fetch.d.ts +22 -0
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +82 -0
- package/dist/fetch.test.d.ts +2 -0
- package/dist/fetch.test.d.ts.map +1 -0
- package/dist/fetch.test.js +97 -0
- package/dist/fileSystem.d.ts +11 -0
- package/dist/fileSystem.d.ts.map +1 -0
- package/dist/fileSystem.js +42 -0
- package/dist/fileSystem.test.d.ts +2 -0
- package/dist/fileSystem.test.d.ts.map +1 -0
- package/dist/fileSystem.test.js +75 -0
- package/dist/fluent/http2-watch.spec.d.ts +2 -0
- package/dist/fluent/http2-watch.spec.d.ts.map +1 -0
- package/dist/fluent/http2-watch.spec.js +284 -0
- package/dist/fluent/index.d.ts +12 -0
- package/dist/fluent/index.d.ts.map +1 -0
- package/dist/fluent/index.js +228 -0
- package/dist/fluent/index.test.d.ts +2 -0
- package/dist/fluent/index.test.d.ts.map +1 -0
- package/dist/fluent/index.test.js +193 -0
- package/dist/fluent/types.d.ts +201 -0
- package/dist/fluent/types.d.ts.map +1 -0
- package/dist/fluent/types.js +16 -0
- package/dist/fluent/utils.d.ts +41 -0
- package/dist/fluent/utils.d.ts.map +1 -0
- package/dist/fluent/utils.js +153 -0
- package/dist/fluent/utils.test.d.ts +2 -0
- package/dist/fluent/utils.test.d.ts.map +1 -0
- package/dist/fluent/utils.test.js +215 -0
- package/dist/fluent/watch.d.ts +88 -0
- package/dist/fluent/watch.d.ts.map +1 -0
- package/dist/fluent/watch.js +595 -0
- package/dist/fluent/watch.spec.d.ts +2 -0
- package/dist/fluent/watch.spec.d.ts.map +1 -0
- package/dist/fluent/watch.spec.js +261 -0
- package/dist/generate.d.ts +84 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +208 -0
- package/dist/generate.test.d.ts +2 -0
- package/dist/generate.test.d.ts.map +1 -0
- package/dist/generate.test.js +320 -0
- package/dist/helpers.d.ts +33 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +103 -0
- package/dist/helpers.test.d.ts +2 -0
- package/dist/helpers.test.d.ts.map +1 -0
- package/dist/helpers.test.js +37 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/kinds.d.ts +16 -0
- package/dist/kinds.d.ts.map +1 -0
- package/dist/kinds.js +570 -0
- package/dist/kinds.test.d.ts +2 -0
- package/dist/kinds.test.d.ts.map +1 -0
- package/dist/kinds.test.js +155 -0
- package/dist/patch.d.ts +7 -0
- package/dist/patch.d.ts.map +1 -0
- package/dist/patch.js +2 -0
- package/dist/postProcessing.d.ts +246 -0
- package/dist/postProcessing.d.ts.map +1 -0
- package/dist/postProcessing.js +497 -0
- package/dist/postProcessing.test.d.ts +2 -0
- package/dist/postProcessing.test.d.ts.map +1 -0
- package/dist/postProcessing.test.js +550 -0
- package/dist/types.d.ts +32 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/upstream.d.ts +4 -0
- package/dist/upstream.d.ts.map +1 -0
- package/dist/upstream.js +56 -0
- package/package.json +1 -1
- package/src/fluent/types.ts +16 -0
- package/src/fluent/watch.ts +134 -81
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
|
+
const globals_1 = require("@jest/globals");
|
|
8
|
+
const http2_1 = __importDefault(require("http2"));
|
|
9
|
+
const __1 = require("..");
|
|
10
|
+
const types_1 = require("./types");
|
|
11
|
+
const _1 = require(".");
|
|
12
|
+
globals_1.jest.mock("http2");
|
|
13
|
+
(0, globals_1.describe)("Watcher HTTP2", () => {
|
|
14
|
+
let watcher;
|
|
15
|
+
let mockClient;
|
|
16
|
+
let mockReq;
|
|
17
|
+
const evtMock = globals_1.jest.fn();
|
|
18
|
+
const errMock = globals_1.jest.fn();
|
|
19
|
+
const setupAndStartWatcher = (eventType, handler) => {
|
|
20
|
+
watcher.events.on(eventType, handler);
|
|
21
|
+
watcher.start().catch(errMock);
|
|
22
|
+
};
|
|
23
|
+
(0, globals_1.beforeEach)(() => {
|
|
24
|
+
globals_1.jest.clearAllMocks();
|
|
25
|
+
// http2.client
|
|
26
|
+
mockClient = {
|
|
27
|
+
request: globals_1.jest.fn(),
|
|
28
|
+
close: globals_1.jest.fn(),
|
|
29
|
+
on: globals_1.jest.fn(),
|
|
30
|
+
destroy: globals_1.jest.fn(),
|
|
31
|
+
};
|
|
32
|
+
// http2.request stream
|
|
33
|
+
mockReq = {
|
|
34
|
+
on: globals_1.jest.fn(),
|
|
35
|
+
end: globals_1.jest.fn(),
|
|
36
|
+
setEncoding: globals_1.jest.fn(),
|
|
37
|
+
};
|
|
38
|
+
// http2.connect function to return the mocked client session
|
|
39
|
+
http2_1.default.connect.mockReturnValue(mockClient);
|
|
40
|
+
});
|
|
41
|
+
(0, globals_1.afterEach)(() => {
|
|
42
|
+
watcher.close();
|
|
43
|
+
});
|
|
44
|
+
(0, globals_1.it)("should watch named resources", done => {
|
|
45
|
+
const pod = createMockPod("pod-1", "1");
|
|
46
|
+
const response = { type: "ADDED", object: pod };
|
|
47
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch(evtMock, {
|
|
48
|
+
useHTTP2: true,
|
|
49
|
+
});
|
|
50
|
+
mockReq.on.mockImplementation((event, callback) => {
|
|
51
|
+
switch (event) {
|
|
52
|
+
case "response":
|
|
53
|
+
callback({ ":status": 200 }, 0);
|
|
54
|
+
break;
|
|
55
|
+
case "data":
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
callback(Buffer.from(JSON.stringify(response)));
|
|
58
|
+
}, 10);
|
|
59
|
+
break;
|
|
60
|
+
case "end":
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
callback();
|
|
63
|
+
done();
|
|
64
|
+
}, 20);
|
|
65
|
+
break;
|
|
66
|
+
case "error":
|
|
67
|
+
errMock(new Error("HTTP2 connection error"));
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
return mockReq;
|
|
71
|
+
});
|
|
72
|
+
mockClient.request.mockReturnValue(mockReq);
|
|
73
|
+
setupAndStartWatcher(__1.WatchEvent.CONNECT, () => {
|
|
74
|
+
setupAndStartWatcher(__1.WatchEvent.DATA, (receivedPod, phase) => {
|
|
75
|
+
(0, globals_1.expect)(receivedPod.metadata?.name).toBe("pod-1");
|
|
76
|
+
(0, globals_1.expect)(receivedPod.metadata?.resourceVersion).toBe("1");
|
|
77
|
+
(0, globals_1.expect)(phase).toBe(types_1.WatchPhase.Added);
|
|
78
|
+
done();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
(0, globals_1.it)("should handle resource version is too old", done => {
|
|
83
|
+
const errorResponse = {
|
|
84
|
+
type: "ERROR",
|
|
85
|
+
object: {
|
|
86
|
+
kind: "Status",
|
|
87
|
+
apiVersion: "v1",
|
|
88
|
+
metadata: {},
|
|
89
|
+
status: "Failure",
|
|
90
|
+
message: "too old resource version: 123 (391079)",
|
|
91
|
+
reason: "Gone",
|
|
92
|
+
code: 410,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch(evtMock, {
|
|
96
|
+
useHTTP2: true,
|
|
97
|
+
});
|
|
98
|
+
mockReq.on.mockImplementation((event, callback) => {
|
|
99
|
+
switch (event) {
|
|
100
|
+
case "response":
|
|
101
|
+
callback({ ":status": 200 }, 0);
|
|
102
|
+
break;
|
|
103
|
+
case "data":
|
|
104
|
+
setTimeout(() => {
|
|
105
|
+
callback(Buffer.from(JSON.stringify(errorResponse)));
|
|
106
|
+
}, 10);
|
|
107
|
+
break;
|
|
108
|
+
case "end":
|
|
109
|
+
setTimeout(() => {
|
|
110
|
+
callback();
|
|
111
|
+
done();
|
|
112
|
+
}, 20);
|
|
113
|
+
break;
|
|
114
|
+
case "error":
|
|
115
|
+
errMock(new Error("HTTP2 connection error"));
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
return mockReq;
|
|
119
|
+
});
|
|
120
|
+
mockClient.request.mockReturnValue(mockReq);
|
|
121
|
+
setupAndStartWatcher(__1.WatchEvent.OLD_RESOURCE_VERSION, res => {
|
|
122
|
+
(0, globals_1.expect)(res).toEqual("123");
|
|
123
|
+
done();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
(0, globals_1.it)("should call the event handler for each event", done => {
|
|
127
|
+
const pod = createMockPod("pod-0", "1");
|
|
128
|
+
const response = { type: "ADDED", object: pod };
|
|
129
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch((evt, phase) => {
|
|
130
|
+
(0, globals_1.expect)(evt.metadata?.name).toEqual("pod-0");
|
|
131
|
+
(0, globals_1.expect)(phase).toEqual(types_1.WatchPhase.Added);
|
|
132
|
+
}, { useHTTP2: true });
|
|
133
|
+
mockReq.on.mockImplementation((event, callback) => {
|
|
134
|
+
switch (event) {
|
|
135
|
+
case "response":
|
|
136
|
+
callback({ ":status": 200 }, 0);
|
|
137
|
+
break;
|
|
138
|
+
case "data":
|
|
139
|
+
setTimeout(() => {
|
|
140
|
+
callback(Buffer.from(JSON.stringify(response)));
|
|
141
|
+
}, 10);
|
|
142
|
+
break;
|
|
143
|
+
case "end":
|
|
144
|
+
setTimeout(() => {
|
|
145
|
+
callback();
|
|
146
|
+
}, 20);
|
|
147
|
+
break;
|
|
148
|
+
case "error":
|
|
149
|
+
errMock(new Error("HTTP2 connection error"));
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
return mockReq;
|
|
153
|
+
});
|
|
154
|
+
mockClient.request.mockReturnValue(mockReq);
|
|
155
|
+
watcher.start().catch(errMock);
|
|
156
|
+
done();
|
|
157
|
+
});
|
|
158
|
+
(0, globals_1.it)("should return the cache id", () => {
|
|
159
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch(evtMock, {
|
|
160
|
+
resyncDelaySec: 1,
|
|
161
|
+
useHTTP2: true,
|
|
162
|
+
});
|
|
163
|
+
(0, globals_1.expect)(watcher.getCacheID()).toEqual("d69b75a611");
|
|
164
|
+
});
|
|
165
|
+
(0, globals_1.it)("should handle the CONNECT event", done => {
|
|
166
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch(evtMock, {
|
|
167
|
+
resyncDelaySec: 1,
|
|
168
|
+
useHTTP2: true,
|
|
169
|
+
});
|
|
170
|
+
setupAndStartWatcher(__1.WatchEvent.CONNECT, () => { });
|
|
171
|
+
done();
|
|
172
|
+
});
|
|
173
|
+
(0, globals_1.it)("should handle the DATA event", done => {
|
|
174
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch(evtMock, {
|
|
175
|
+
resyncDelaySec: 1,
|
|
176
|
+
useHTTP2: true,
|
|
177
|
+
});
|
|
178
|
+
setupAndStartWatcher(__1.WatchEvent.DATA, (pod, phase) => {
|
|
179
|
+
(0, globals_1.expect)(pod.metadata?.name).toEqual("pod-0");
|
|
180
|
+
(0, globals_1.expect)(phase).toEqual(types_1.WatchPhase.Added);
|
|
181
|
+
});
|
|
182
|
+
done();
|
|
183
|
+
});
|
|
184
|
+
(0, globals_1.it)("should handle the NETWORK_ERROR event", done => {
|
|
185
|
+
const errorMessage = "Something bad happened";
|
|
186
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch(evtMock, {
|
|
187
|
+
useHTTP2: true,
|
|
188
|
+
resyncDelaySec: 1,
|
|
189
|
+
});
|
|
190
|
+
mockReq.on.mockImplementation((event, callback) => {
|
|
191
|
+
if (event === "response") {
|
|
192
|
+
callback({ ":status": 200 }, 0);
|
|
193
|
+
}
|
|
194
|
+
else if (event === "error") {
|
|
195
|
+
callback(new Error(errorMessage));
|
|
196
|
+
}
|
|
197
|
+
return mockReq;
|
|
198
|
+
});
|
|
199
|
+
mockClient.request.mockReturnValue(mockReq);
|
|
200
|
+
setupAndStartWatcher(__1.WatchEvent.NETWORK_ERROR, error => {
|
|
201
|
+
(0, globals_1.expect)(error.message).toEqual(errorMessage);
|
|
202
|
+
});
|
|
203
|
+
watcher.start().catch(errMock);
|
|
204
|
+
done();
|
|
205
|
+
});
|
|
206
|
+
(0, globals_1.it)("should handle the RECONNECT event on an error", done => {
|
|
207
|
+
const errorMessage = "Something bad happened";
|
|
208
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch(evtMock, {
|
|
209
|
+
useHTTP2: true,
|
|
210
|
+
resyncDelaySec: 0.01,
|
|
211
|
+
});
|
|
212
|
+
let reconnectCount = 0;
|
|
213
|
+
mockReq.on.mockImplementation((event, callback) => {
|
|
214
|
+
if (event === "response") {
|
|
215
|
+
callback({ ":status": 200 }, 0);
|
|
216
|
+
}
|
|
217
|
+
else if (event === "error") {
|
|
218
|
+
reconnectCount += 1;
|
|
219
|
+
callback(new Error(errorMessage));
|
|
220
|
+
}
|
|
221
|
+
return mockReq;
|
|
222
|
+
});
|
|
223
|
+
mockClient.request.mockReturnValue(mockReq);
|
|
224
|
+
setupAndStartWatcher(__1.WatchEvent.RECONNECT, count => {
|
|
225
|
+
(0, globals_1.expect)(count).toEqual(reconnectCount);
|
|
226
|
+
});
|
|
227
|
+
watcher.start().catch(errMock);
|
|
228
|
+
done();
|
|
229
|
+
});
|
|
230
|
+
(0, globals_1.it)("should perform a resync after the resync interval", done => {
|
|
231
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch(evtMock, {
|
|
232
|
+
useHTTP2: true,
|
|
233
|
+
resyncDelaySec: 1,
|
|
234
|
+
});
|
|
235
|
+
watcher.start().catch(errMock);
|
|
236
|
+
done();
|
|
237
|
+
});
|
|
238
|
+
(0, globals_1.it)("should handle the GIVE_UP event", done => {
|
|
239
|
+
watcher = (0, _1.K8s)(__1.kind.Pod).Watch(evtMock, {
|
|
240
|
+
useHTTP2: true,
|
|
241
|
+
lastSeenLimitSeconds: 0.01,
|
|
242
|
+
resyncDelaySec: 0.01,
|
|
243
|
+
resyncFailureMax: 1,
|
|
244
|
+
});
|
|
245
|
+
setupAndStartWatcher(__1.WatchEvent.GIVE_UP, () => {
|
|
246
|
+
(0, globals_1.expect)(errMock).toBeCalled();
|
|
247
|
+
});
|
|
248
|
+
watcher.start().catch(errMock);
|
|
249
|
+
done();
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
/**
|
|
253
|
+
* Creates a mock pod object
|
|
254
|
+
*
|
|
255
|
+
* @param name The name of the pod
|
|
256
|
+
* @param resourceVersion The resource version of the pod
|
|
257
|
+
* @returns A mock pod object
|
|
258
|
+
*/
|
|
259
|
+
function createMockPod(name, resourceVersion) {
|
|
260
|
+
return {
|
|
261
|
+
kind: "Pod",
|
|
262
|
+
apiVersion: "v1",
|
|
263
|
+
metadata: {
|
|
264
|
+
name,
|
|
265
|
+
resourceVersion,
|
|
266
|
+
uid: "abc-123-xyz",
|
|
267
|
+
},
|
|
268
|
+
spec: {
|
|
269
|
+
containers: [
|
|
270
|
+
{
|
|
271
|
+
name: "nginx",
|
|
272
|
+
image: "nginx:1.14.2",
|
|
273
|
+
ports: [
|
|
274
|
+
{
|
|
275
|
+
containerPort: 80,
|
|
276
|
+
protocol: "TCP",
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
},
|
|
282
|
+
status: {},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { KubernetesObject } from "@kubernetes/client-node";
|
|
2
|
+
import { GenericClass } from "../types";
|
|
3
|
+
import { Filters, K8sInit } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* Kubernetes fluent API inspired by Kubectl. Pass in a model, then call filters and actions on it.
|
|
6
|
+
*
|
|
7
|
+
* @param model - the model to use for the API
|
|
8
|
+
* @param filters - (optional) filter overrides, can also be chained
|
|
9
|
+
* @returns a fluent API for the model
|
|
10
|
+
*/
|
|
11
|
+
export declare function K8s<T extends GenericClass, K extends KubernetesObject = InstanceType<T>>(model: T, filters?: Filters): K8sInit<T, K>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fluent/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAwB,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAOjF,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAA0B,OAAO,EAAE,OAAO,EAAsB,MAAM,SAAS,CAAC;AAKvF;;;;;;GAMG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,gBAAgB,GAAG,YAAY,CAAC,CAAC,CAAC,EACtF,KAAK,EAAE,CAAC,EACR,OAAO,GAAE,OAAY,GACpB,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CA0Pf"}
|
|
@@ -0,0 +1,228 @@
|
|
|
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
|
+
exports.K8s = K8s;
|
|
6
|
+
const http_status_codes_1 = require("http-status-codes");
|
|
7
|
+
const fetch_1 = require("../fetch");
|
|
8
|
+
const kinds_1 = require("../kinds");
|
|
9
|
+
const utils_1 = require("./utils");
|
|
10
|
+
const watch_1 = require("./watch");
|
|
11
|
+
const helpers_1 = require("../helpers");
|
|
12
|
+
const upstream_1 = require("../upstream");
|
|
13
|
+
/**
|
|
14
|
+
* Kubernetes fluent API inspired by Kubectl. Pass in a model, then call filters and actions on it.
|
|
15
|
+
*
|
|
16
|
+
* @param model - the model to use for the API
|
|
17
|
+
* @param filters - (optional) filter overrides, can also be chained
|
|
18
|
+
* @returns a fluent API for the model
|
|
19
|
+
*/
|
|
20
|
+
function K8s(model, filters = {}) {
|
|
21
|
+
const withFilters = { WithField, WithLabel, Get, Delete, Watch, Logs };
|
|
22
|
+
const matchedKind = filters.kindOverride || (0, kinds_1.modelToGroupVersionKind)(model.name);
|
|
23
|
+
/**
|
|
24
|
+
* @inheritdoc
|
|
25
|
+
* @see {@link K8sInit.InNamespace}
|
|
26
|
+
*/
|
|
27
|
+
function InNamespace(namespace) {
|
|
28
|
+
if (filters.namespace) {
|
|
29
|
+
throw new Error(`Namespace already specified: ${filters.namespace}`);
|
|
30
|
+
}
|
|
31
|
+
filters.namespace = namespace;
|
|
32
|
+
return withFilters;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @inheritdoc
|
|
36
|
+
* @see {@link K8sInit.WithField}
|
|
37
|
+
*/
|
|
38
|
+
function WithField(key, value) {
|
|
39
|
+
filters.fields = filters.fields || {};
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
filters.fields[key] = value;
|
|
43
|
+
return withFilters;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* @inheritdoc
|
|
47
|
+
* @see {@link K8sInit.WithLabel}
|
|
48
|
+
*/
|
|
49
|
+
function WithLabel(key, value = "") {
|
|
50
|
+
filters.labels = filters.labels || {};
|
|
51
|
+
filters.labels[key] = value;
|
|
52
|
+
return withFilters;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Sync the filters with the provided payload.
|
|
56
|
+
*
|
|
57
|
+
* @param payload - the payload to sync with
|
|
58
|
+
*/
|
|
59
|
+
function syncFilters(payload) {
|
|
60
|
+
// Ensure the payload has metadata
|
|
61
|
+
payload.metadata = payload.metadata || {};
|
|
62
|
+
if (!filters.namespace) {
|
|
63
|
+
filters.namespace = payload.metadata.namespace;
|
|
64
|
+
}
|
|
65
|
+
if (!filters.name) {
|
|
66
|
+
filters.name = payload.metadata.name;
|
|
67
|
+
}
|
|
68
|
+
if (!payload.apiVersion) {
|
|
69
|
+
payload.apiVersion = [matchedKind.group, matchedKind.version].filter(Boolean).join("/");
|
|
70
|
+
}
|
|
71
|
+
if (!payload.kind) {
|
|
72
|
+
payload.kind = matchedKind.kind;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* @inheritdoc
|
|
77
|
+
* @see {@link K8sInit.Logs}
|
|
78
|
+
*/
|
|
79
|
+
async function Logs(name) {
|
|
80
|
+
let labels = {};
|
|
81
|
+
const { kind } = matchedKind;
|
|
82
|
+
const { namespace } = filters;
|
|
83
|
+
const podList = [];
|
|
84
|
+
if (name) {
|
|
85
|
+
if (filters.name) {
|
|
86
|
+
throw new Error(`Name already specified: ${filters.name}`);
|
|
87
|
+
}
|
|
88
|
+
filters.name = name;
|
|
89
|
+
}
|
|
90
|
+
if (!namespace) {
|
|
91
|
+
throw new Error("Namespace must be defined");
|
|
92
|
+
}
|
|
93
|
+
if (!(0, helpers_1.hasLogs)(kind)) {
|
|
94
|
+
throw new Error("Kind must be Pod or have a selector");
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const object = await (0, utils_1.k8sExec)(model, filters, "GET");
|
|
98
|
+
if (kind !== "Pod") {
|
|
99
|
+
if (kind === "Service") {
|
|
100
|
+
const svc = object;
|
|
101
|
+
labels = svc.spec.selector ?? {};
|
|
102
|
+
}
|
|
103
|
+
else if (kind === "ReplicaSet" ||
|
|
104
|
+
kind === "Deployment" ||
|
|
105
|
+
kind === "StatefulSet" ||
|
|
106
|
+
kind === "DaemonSet") {
|
|
107
|
+
const rs = object;
|
|
108
|
+
labels = rs.spec.selector.matchLabels ?? {};
|
|
109
|
+
}
|
|
110
|
+
const list = await K8s(upstream_1.Pod, { namespace: filters.namespace, labels }).Get();
|
|
111
|
+
list.items.forEach(item => {
|
|
112
|
+
return podList.push(item);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
podList.push(object);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
throw new Error(`Failed to get logs in KFC Logs function`);
|
|
121
|
+
}
|
|
122
|
+
const podModel = { ...model, name: "V1Pod" };
|
|
123
|
+
const logPromises = podList.map(po => (0, utils_1.k8sExec)(podModel, { ...filters, name: po.metadata.name }, "LOG"));
|
|
124
|
+
const responses = await Promise.all(logPromises);
|
|
125
|
+
const combinedString = responses.reduce((accumulator, currentString, i) => {
|
|
126
|
+
const prefixedLines = currentString
|
|
127
|
+
.split("\n")
|
|
128
|
+
.map(line => {
|
|
129
|
+
return line !== "" ? `[pod/${podList[i].metadata.name}] ${line}` : "";
|
|
130
|
+
})
|
|
131
|
+
.filter(str => str !== "");
|
|
132
|
+
return [...accumulator, ...prefixedLines];
|
|
133
|
+
}, []);
|
|
134
|
+
return combinedString;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* @inheritdoc
|
|
138
|
+
* @see {@link K8sInit.Get}
|
|
139
|
+
*/
|
|
140
|
+
async function Get(name) {
|
|
141
|
+
if (name) {
|
|
142
|
+
if (filters.name) {
|
|
143
|
+
throw new Error(`Name already specified: ${filters.name}`);
|
|
144
|
+
}
|
|
145
|
+
filters.name = name;
|
|
146
|
+
}
|
|
147
|
+
return (0, utils_1.k8sExec)(model, filters, "GET");
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* @inheritdoc
|
|
151
|
+
* @see {@link K8sInit.Delete}
|
|
152
|
+
*/
|
|
153
|
+
async function Delete(filter) {
|
|
154
|
+
if (typeof filter === "string") {
|
|
155
|
+
filters.name = filter;
|
|
156
|
+
}
|
|
157
|
+
else if (filter) {
|
|
158
|
+
syncFilters(filter);
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
// Try to delete the resource
|
|
162
|
+
await (0, utils_1.k8sExec)(model, filters, "DELETE");
|
|
163
|
+
}
|
|
164
|
+
catch (e) {
|
|
165
|
+
// If the resource doesn't exist, ignore the error
|
|
166
|
+
if (e.status === http_status_codes_1.StatusCodes.NOT_FOUND) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
throw e;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* @inheritdoc
|
|
174
|
+
* @see {@link K8sInit.Apply}
|
|
175
|
+
*/
|
|
176
|
+
async function Apply(resource, applyCfg = { force: false }) {
|
|
177
|
+
syncFilters(resource);
|
|
178
|
+
return (0, utils_1.k8sExec)(model, filters, "APPLY", resource, applyCfg);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* @inheritdoc
|
|
182
|
+
* @see {@link K8sInit.Create}
|
|
183
|
+
*/
|
|
184
|
+
async function Create(resource) {
|
|
185
|
+
syncFilters(resource);
|
|
186
|
+
return (0, utils_1.k8sExec)(model, filters, "POST", resource);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* @inheritdoc
|
|
190
|
+
* @see {@link K8sInit.Patch}
|
|
191
|
+
*/
|
|
192
|
+
async function Patch(payload) {
|
|
193
|
+
// If there are no operations, throw an error
|
|
194
|
+
if (payload.length < 1) {
|
|
195
|
+
throw new Error("No operations specified");
|
|
196
|
+
}
|
|
197
|
+
return (0, utils_1.k8sExec)(model, filters, "PATCH", payload);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* @inheritdoc
|
|
201
|
+
* @see {@link K8sInit.PatchStatus}
|
|
202
|
+
*/
|
|
203
|
+
async function PatchStatus(resource) {
|
|
204
|
+
syncFilters(resource);
|
|
205
|
+
return (0, utils_1.k8sExec)(model, filters, "PATCH_STATUS", resource);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* @inheritdoc
|
|
209
|
+
* @see {@link K8sInit.Watch}
|
|
210
|
+
*/
|
|
211
|
+
function Watch(callback, watchCfg) {
|
|
212
|
+
return new watch_1.Watcher(model, filters, callback, watchCfg);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* @inheritdoc
|
|
216
|
+
* @see {@link K8sInit.Raw}
|
|
217
|
+
*/
|
|
218
|
+
async function Raw(url, method = "GET") {
|
|
219
|
+
const thing = await (0, utils_1.k8sCfg)(method);
|
|
220
|
+
const { opts, serverUrl } = thing;
|
|
221
|
+
const resp = await (0, fetch_1.fetch)(`${serverUrl}${url}`, opts);
|
|
222
|
+
if (resp.ok) {
|
|
223
|
+
return resp.data;
|
|
224
|
+
}
|
|
225
|
+
throw resp;
|
|
226
|
+
}
|
|
227
|
+
return { InNamespace, Apply, Create, Patch, PatchStatus, Raw, ...withFilters };
|
|
228
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/fluent/index.test.ts"],"names":[],"mappings":""}
|