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,193 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { KubernetesListObject, KubernetesObject } from "@kubernetes/client-node";
|
|
2
|
+
import { Operation } from "fast-json-patch";
|
|
3
|
+
import type { PartialDeep } from "type-fest";
|
|
4
|
+
import { GenericClass, GroupVersionKind } from "../types";
|
|
5
|
+
import { WatchCfg, Watcher } from "./watch";
|
|
6
|
+
import https from "https";
|
|
7
|
+
import { SecureClientSessionOptions } from "http2";
|
|
8
|
+
/**
|
|
9
|
+
* Agent options for the the http2Watch
|
|
10
|
+
*/
|
|
11
|
+
export type AgentOptions = Pick<SecureClientSessionOptions, "ca" | "cert" | "key" | "rejectUnauthorized">;
|
|
12
|
+
/**
|
|
13
|
+
* Options for the http2Watch
|
|
14
|
+
*/
|
|
15
|
+
export interface Options {
|
|
16
|
+
agent?: https.Agent & {
|
|
17
|
+
options?: AgentOptions;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The Phase matched when using the K8s Watch API.
|
|
22
|
+
*/
|
|
23
|
+
export declare enum WatchPhase {
|
|
24
|
+
Added = "ADDED",
|
|
25
|
+
Modified = "MODIFIED",
|
|
26
|
+
Deleted = "DELETED",
|
|
27
|
+
Bookmark = "BOOKMARK",
|
|
28
|
+
Error = "ERROR"
|
|
29
|
+
}
|
|
30
|
+
export type FetchMethods = "GET" | "APPLY" | "POST" | "PUT" | "DELETE" | "PATCH" | "WATCH" | "PATCH_STATUS" | "LOG";
|
|
31
|
+
export interface Filters {
|
|
32
|
+
kindOverride?: GroupVersionKind;
|
|
33
|
+
fields?: Record<string, string>;
|
|
34
|
+
labels?: Record<string, string>;
|
|
35
|
+
name?: string;
|
|
36
|
+
namespace?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get the resource or resources matching the filters.
|
|
40
|
+
* If no filters are specified, all resources will be returned.
|
|
41
|
+
* If a name is specified, only a single resource will be returned.
|
|
42
|
+
*
|
|
43
|
+
* @param name - (optional) the name of the resource to get
|
|
44
|
+
* @returns the resource or list of resources
|
|
45
|
+
*/
|
|
46
|
+
export type GetFunction<K extends KubernetesObject> = {
|
|
47
|
+
(): Promise<KubernetesListObject<K>>;
|
|
48
|
+
(name: string): Promise<K>;
|
|
49
|
+
};
|
|
50
|
+
export type K8sFilteredActions<T extends GenericClass, K extends KubernetesObject> = {
|
|
51
|
+
/**
|
|
52
|
+
* Gets the logs.
|
|
53
|
+
*
|
|
54
|
+
* @param name - the name of the Object to get logs from
|
|
55
|
+
* @returns array of logs
|
|
56
|
+
*/
|
|
57
|
+
Logs: (name: string) => Promise<string[]>;
|
|
58
|
+
/**
|
|
59
|
+
* Get the resource or resources matching the filters.
|
|
60
|
+
* If no filters are specified, all resources will be returned.
|
|
61
|
+
* If a name is specified, only a single resource will be returned.
|
|
62
|
+
*/
|
|
63
|
+
Get: GetFunction<K>;
|
|
64
|
+
/**
|
|
65
|
+
* Delete the resource matching the filters.
|
|
66
|
+
*
|
|
67
|
+
* @param filter - the resource or resource name to delete
|
|
68
|
+
*/
|
|
69
|
+
Delete: (filter?: K | string) => Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Watch the resource matching the filters.
|
|
72
|
+
*
|
|
73
|
+
* @param callback - the callback function to call when an event occurs
|
|
74
|
+
* @param watchCfg - (optional) watch configuration
|
|
75
|
+
* @returns a watch controller
|
|
76
|
+
*/
|
|
77
|
+
Watch: (callback: WatchAction<T>, watchCfg?: WatchCfg) => Watcher<T>;
|
|
78
|
+
};
|
|
79
|
+
export type K8sUnfilteredActions<K extends KubernetesObject> = {
|
|
80
|
+
/**
|
|
81
|
+
* Perform a server-side apply of the provided K8s resource.
|
|
82
|
+
*
|
|
83
|
+
* @param resource - the resource to apply
|
|
84
|
+
* @param applyCfg - (optional) apply configuration
|
|
85
|
+
* @returns the applied resource
|
|
86
|
+
*/
|
|
87
|
+
Apply: (resource: PartialDeep<K>, applyCfg?: ApplyCfg) => Promise<K>;
|
|
88
|
+
/**
|
|
89
|
+
* Create the provided K8s resource or throw an error if it already exists.
|
|
90
|
+
*
|
|
91
|
+
* @param resource - the resource to create
|
|
92
|
+
* @returns the created resource
|
|
93
|
+
*/
|
|
94
|
+
Create: (resource: K) => Promise<K>;
|
|
95
|
+
/**
|
|
96
|
+
* Advanced JSON Patch operations for when Server Side Apply, K8s().Apply(), is insufficient.
|
|
97
|
+
*
|
|
98
|
+
* Note: Throws an error on an empty list of patch operations.
|
|
99
|
+
*
|
|
100
|
+
* @param payload The patch operations to run
|
|
101
|
+
* @returns The patched resource
|
|
102
|
+
*/
|
|
103
|
+
Patch: (payload: Operation[]) => Promise<K>;
|
|
104
|
+
/**
|
|
105
|
+
* Patch the status of the provided K8s resource. Note this is a special case of the Patch method that
|
|
106
|
+
* only allows patching the status subresource. This can be used in Operator reconciliation loops to
|
|
107
|
+
* update the status of a resource without triggering a new Generation of the resource.
|
|
108
|
+
*
|
|
109
|
+
* See https://stackoverflow.com/q/47100389/467373 for more details.
|
|
110
|
+
*
|
|
111
|
+
* IMPORTANT: This method will throw a 404 error if the resource does not have a status subresource defined.
|
|
112
|
+
*
|
|
113
|
+
* @param resource - the resource to patch
|
|
114
|
+
* @returns the patched resource
|
|
115
|
+
*/
|
|
116
|
+
PatchStatus: (resource: PartialDeep<K>) => Promise<K>;
|
|
117
|
+
/**
|
|
118
|
+
* Perform a raw GET request to the Kubernetes API. This is useful for calling endpoints that are not supported by the fluent API.
|
|
119
|
+
* This command mirrors the `kubectl get --raw` command.
|
|
120
|
+
*
|
|
121
|
+
* E.g.
|
|
122
|
+
*
|
|
123
|
+
* ```ts
|
|
124
|
+
* import { V1APIGroup } from "@kubernetes/client-node";
|
|
125
|
+
*
|
|
126
|
+
* K8s(V1APIGroup).Raw("/api")
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* will call the `/api` endpoint and is equivalent to `kubectl get --raw /api`.
|
|
130
|
+
*
|
|
131
|
+
* @param url the URL to call (e.g. /api)
|
|
132
|
+
* @returns
|
|
133
|
+
*/
|
|
134
|
+
Raw: (url: string, method?: FetchMethods) => Promise<K>;
|
|
135
|
+
};
|
|
136
|
+
export type K8sWithFilters<T extends GenericClass, K extends KubernetesObject> = K8sFilteredActions<T, K> & {
|
|
137
|
+
/**
|
|
138
|
+
* Filter the query by the given field.
|
|
139
|
+
* Note multiple calls to this method will result in an AND condition. e.g.
|
|
140
|
+
*
|
|
141
|
+
* ```ts
|
|
142
|
+
* K8s(kind.Deployment)
|
|
143
|
+
* .WithField("metadata.name", "bar")
|
|
144
|
+
* .WithField("metadata.namespace", "qux")
|
|
145
|
+
* .Delete(...)
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* Will only delete the Deployment if it has the `metadata.name=bar` and `metadata.namespace=qux` fields.
|
|
149
|
+
* Not all fields are supported, see https://kubernetes.io/docs/concepts/overview/working-with-objects/field-selectors/#supported-fields,
|
|
150
|
+
* but Typescript will limit to only fields that exist on the resource.
|
|
151
|
+
*
|
|
152
|
+
* @param key - the field key
|
|
153
|
+
* @param value - the field value
|
|
154
|
+
* @returns the fluent API
|
|
155
|
+
*/
|
|
156
|
+
WithField: <P extends Paths<K>>(key: P, value: string) => K8sWithFilters<T, K>;
|
|
157
|
+
/**
|
|
158
|
+
* Filter the query by the given label. If no value is specified, the label simply must exist.
|
|
159
|
+
* Note multiple calls to this method will result in an AND condition. e.g.
|
|
160
|
+
*
|
|
161
|
+
* ```ts
|
|
162
|
+
* K8s(kind.Deployment)
|
|
163
|
+
* .WithLabel("foo", "bar")
|
|
164
|
+
* .WithLabel("baz", "qux")
|
|
165
|
+
* .WithLabel("quux")
|
|
166
|
+
* .Delete(...)
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
169
|
+
* Will only delete the Deployment if it has the`foo=bar` and `baz=qux` labels and the `quux` label exists.
|
|
170
|
+
*
|
|
171
|
+
* @param key - the label key
|
|
172
|
+
* @param value - the label value
|
|
173
|
+
* @returns the fluent API
|
|
174
|
+
*/
|
|
175
|
+
WithLabel: (key: string, value?: string) => K8sWithFilters<T, K>;
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Configuration for the apply function.
|
|
179
|
+
*/
|
|
180
|
+
export type ApplyCfg = {
|
|
181
|
+
/**
|
|
182
|
+
* Force the apply to be a create.
|
|
183
|
+
*/
|
|
184
|
+
force?: boolean;
|
|
185
|
+
};
|
|
186
|
+
export type K8sInit<T extends GenericClass, K extends KubernetesObject> = K8sWithFilters<T, K> & K8sUnfilteredActions<K> & {
|
|
187
|
+
/**
|
|
188
|
+
* Set the namespace filter.
|
|
189
|
+
*
|
|
190
|
+
* @param namespace - the namespace to filter on
|
|
191
|
+
* @returns the fluent API
|
|
192
|
+
*/
|
|
193
|
+
InNamespace: (namespace: string) => K8sWithFilters<T, K>;
|
|
194
|
+
};
|
|
195
|
+
export type WatchAction<T extends GenericClass, K extends KubernetesObject = InstanceType<T>> = (update: K, phase: WatchPhase) => Promise<void> | void;
|
|
196
|
+
type Join<K, P> = K extends string | number ? P extends string | number ? `${K}${"" extends P ? "" : "."}${P}` : never : never;
|
|
197
|
+
export type Paths<T, D extends number = 10> = [D] extends [never] ? never : T extends object ? {
|
|
198
|
+
[K in keyof T]-?: K extends string | number ? `${K}` | Join<K, Paths<T[K]>> : never;
|
|
199
|
+
}[keyof T] : "";
|
|
200
|
+
export {};
|
|
201
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/fluent/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
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.WatchPhase = void 0;
|
|
6
|
+
/**
|
|
7
|
+
* The Phase matched when using the K8s Watch API.
|
|
8
|
+
*/
|
|
9
|
+
var WatchPhase;
|
|
10
|
+
(function (WatchPhase) {
|
|
11
|
+
WatchPhase["Added"] = "ADDED";
|
|
12
|
+
WatchPhase["Modified"] = "MODIFIED";
|
|
13
|
+
WatchPhase["Deleted"] = "DELETED";
|
|
14
|
+
WatchPhase["Bookmark"] = "BOOKMARK";
|
|
15
|
+
WatchPhase["Error"] = "ERROR";
|
|
16
|
+
})(WatchPhase || (exports.WatchPhase = WatchPhase = {}));
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { URL } from "url";
|
|
2
|
+
import { GenericClass } from "../types";
|
|
3
|
+
import { ApplyCfg, FetchMethods, Filters } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* Generate a path to a Kubernetes resource
|
|
6
|
+
*
|
|
7
|
+
* @param serverUrl - the URL of the Kubernetes API server
|
|
8
|
+
* @param model - the model to use for the API
|
|
9
|
+
* @param filters - (optional) filter overrides, can also be chained
|
|
10
|
+
* @param excludeName - (optional) exclude the name from the path
|
|
11
|
+
* @returns the path to the resource
|
|
12
|
+
*/
|
|
13
|
+
export declare function pathBuilder<T extends GenericClass>(serverUrl: string, model: T, filters: Filters, excludeName?: boolean): URL;
|
|
14
|
+
/**
|
|
15
|
+
* Sets up the kubeconfig and https agent for a request
|
|
16
|
+
*
|
|
17
|
+
* A few notes:
|
|
18
|
+
* - The kubeconfig is loaded from the default location, and can check for in-cluster config
|
|
19
|
+
* - We have to create an agent to handle the TLS connection (for the custom CA + mTLS in some cases)
|
|
20
|
+
* - The K8s lib uses request instead of node-fetch today so the object is slightly different
|
|
21
|
+
*
|
|
22
|
+
* @param method - the HTTP method to use
|
|
23
|
+
* @returns the fetch options and server URL
|
|
24
|
+
*/
|
|
25
|
+
export declare function k8sCfg(method: FetchMethods): Promise<{
|
|
26
|
+
opts: import("node-fetch").RequestInit;
|
|
27
|
+
serverUrl: string;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Execute a request against the Kubernetes API server.
|
|
31
|
+
*
|
|
32
|
+
* @param model - the model to use for the API
|
|
33
|
+
* @param filters - (optional) filter overrides, can also be chained
|
|
34
|
+
* @param method - the HTTP method to use
|
|
35
|
+
* @param payload - (optional) the payload to send
|
|
36
|
+
* @param applyCfg - (optional) configuration for the apply method
|
|
37
|
+
*
|
|
38
|
+
* @returns the parsed JSON response
|
|
39
|
+
*/
|
|
40
|
+
export declare function k8sExec<T extends GenericClass, K>(model: T, filters: Filters, method: FetchMethods, payload?: K | unknown, applyCfg?: ApplyCfg): Promise<K>;
|
|
41
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/fluent/utils.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAI1B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAI1D;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,YAAY,EAChD,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,OAAO,EAChB,WAAW,UAAQ,OAwDpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY;;;GAwBhD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,OAAO,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,EACrD,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,CAAC,GAAG,OAAO,EACrB,QAAQ,GAAE,QAA2B,cAwDtC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
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.pathBuilder = pathBuilder;
|
|
6
|
+
exports.k8sCfg = k8sCfg;
|
|
7
|
+
exports.k8sExec = k8sExec;
|
|
8
|
+
const client_node_1 = require("@kubernetes/client-node");
|
|
9
|
+
const url_1 = require("url");
|
|
10
|
+
const fetch_1 = require("../fetch");
|
|
11
|
+
const kinds_1 = require("../kinds");
|
|
12
|
+
const SSA_CONTENT_TYPE = "application/apply-patch+yaml";
|
|
13
|
+
/**
|
|
14
|
+
* Generate a path to a Kubernetes resource
|
|
15
|
+
*
|
|
16
|
+
* @param serverUrl - the URL of the Kubernetes API server
|
|
17
|
+
* @param model - the model to use for the API
|
|
18
|
+
* @param filters - (optional) filter overrides, can also be chained
|
|
19
|
+
* @param excludeName - (optional) exclude the name from the path
|
|
20
|
+
* @returns the path to the resource
|
|
21
|
+
*/
|
|
22
|
+
function pathBuilder(serverUrl, model, filters, excludeName = false) {
|
|
23
|
+
const matchedKind = filters.kindOverride || (0, kinds_1.modelToGroupVersionKind)(model.name);
|
|
24
|
+
// If the kind is not specified and the model is not a KubernetesObject, throw an error
|
|
25
|
+
if (!matchedKind) {
|
|
26
|
+
throw new Error(`Kind not specified for ${model.name}`);
|
|
27
|
+
}
|
|
28
|
+
// Use the plural property if it exists, otherwise use lowercase kind + s
|
|
29
|
+
const plural = matchedKind.plural || `${matchedKind.kind.toLowerCase()}s`;
|
|
30
|
+
let base = "/api/v1";
|
|
31
|
+
// If the kind is not in the core group, add the group and version to the path
|
|
32
|
+
if (matchedKind.group) {
|
|
33
|
+
if (!matchedKind.version) {
|
|
34
|
+
throw new Error(`Version not specified for ${model.name}`);
|
|
35
|
+
}
|
|
36
|
+
base = `/apis/${matchedKind.group}/${matchedKind.version}`;
|
|
37
|
+
}
|
|
38
|
+
// Namespaced paths require a namespace prefix
|
|
39
|
+
const namespace = filters.namespace ? `namespaces/${filters.namespace}` : "";
|
|
40
|
+
// Name should not be included in some paths
|
|
41
|
+
const name = excludeName ? "" : filters.name;
|
|
42
|
+
// Build the complete path to the resource
|
|
43
|
+
const path = [base, namespace, plural, name].filter(Boolean).join("/");
|
|
44
|
+
// Generate the URL object
|
|
45
|
+
const url = new url_1.URL(path, serverUrl);
|
|
46
|
+
// Add field selectors to the query params
|
|
47
|
+
if (filters.fields) {
|
|
48
|
+
const fieldSelector = Object.entries(filters.fields)
|
|
49
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
50
|
+
.join(",");
|
|
51
|
+
url.searchParams.set("fieldSelector", fieldSelector);
|
|
52
|
+
}
|
|
53
|
+
// Add label selectors to the query params
|
|
54
|
+
if (filters.labels) {
|
|
55
|
+
const labelSelector = Object.entries(filters.labels)
|
|
56
|
+
// Exists set-based operators only include the key
|
|
57
|
+
// See https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#set-based-requirement
|
|
58
|
+
.map(([key, value]) => (value ? `${key}=${value}` : key))
|
|
59
|
+
.join(",");
|
|
60
|
+
url.searchParams.set("labelSelector", labelSelector);
|
|
61
|
+
}
|
|
62
|
+
return url;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Sets up the kubeconfig and https agent for a request
|
|
66
|
+
*
|
|
67
|
+
* A few notes:
|
|
68
|
+
* - The kubeconfig is loaded from the default location, and can check for in-cluster config
|
|
69
|
+
* - We have to create an agent to handle the TLS connection (for the custom CA + mTLS in some cases)
|
|
70
|
+
* - The K8s lib uses request instead of node-fetch today so the object is slightly different
|
|
71
|
+
*
|
|
72
|
+
* @param method - the HTTP method to use
|
|
73
|
+
* @returns the fetch options and server URL
|
|
74
|
+
*/
|
|
75
|
+
async function k8sCfg(method) {
|
|
76
|
+
const kubeConfig = new client_node_1.KubeConfig();
|
|
77
|
+
kubeConfig.loadFromDefault();
|
|
78
|
+
const cluster = kubeConfig.getCurrentCluster();
|
|
79
|
+
if (!cluster) {
|
|
80
|
+
throw new Error("No currently active cluster");
|
|
81
|
+
}
|
|
82
|
+
// Setup the TLS options & auth headers, as needed
|
|
83
|
+
const opts = await kubeConfig.applyToFetchOptions({
|
|
84
|
+
method,
|
|
85
|
+
headers: {
|
|
86
|
+
// Set the default content type to JSON
|
|
87
|
+
"Content-Type": "application/json",
|
|
88
|
+
// Set the user agent like kubectl does
|
|
89
|
+
"User-Agent": `kubernetes-fluent-client`,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
// Enable compression
|
|
93
|
+
opts.compress = true;
|
|
94
|
+
return { opts, serverUrl: cluster.server };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Execute a request against the Kubernetes API server.
|
|
98
|
+
*
|
|
99
|
+
* @param model - the model to use for the API
|
|
100
|
+
* @param filters - (optional) filter overrides, can also be chained
|
|
101
|
+
* @param method - the HTTP method to use
|
|
102
|
+
* @param payload - (optional) the payload to send
|
|
103
|
+
* @param applyCfg - (optional) configuration for the apply method
|
|
104
|
+
*
|
|
105
|
+
* @returns the parsed JSON response
|
|
106
|
+
*/
|
|
107
|
+
async function k8sExec(model, filters, method, payload, applyCfg = { force: false }) {
|
|
108
|
+
const reconstruct = async (method) => {
|
|
109
|
+
const configMethod = method === "LOG" ? "GET" : method;
|
|
110
|
+
const { opts, serverUrl } = await k8sCfg(configMethod);
|
|
111
|
+
const isPost = method === "POST";
|
|
112
|
+
const baseUrl = pathBuilder(serverUrl, model, filters, isPost);
|
|
113
|
+
if (method === "LOG") {
|
|
114
|
+
baseUrl.pathname = `${baseUrl.pathname}/log`;
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
url: baseUrl,
|
|
118
|
+
opts,
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const { opts, url } = await reconstruct(method);
|
|
122
|
+
switch (opts.method) {
|
|
123
|
+
// PATCH_STATUS is a special case that uses the PATCH method on status subresources
|
|
124
|
+
case "PATCH_STATUS":
|
|
125
|
+
opts.method = "PATCH";
|
|
126
|
+
url.pathname = `${url.pathname}/status`;
|
|
127
|
+
opts.headers.set("Content-Type", client_node_1.PatchStrategy.MergePatch);
|
|
128
|
+
payload = { status: payload.status };
|
|
129
|
+
break;
|
|
130
|
+
case "PATCH":
|
|
131
|
+
opts.headers.set("Content-Type", client_node_1.PatchStrategy.JsonPatch);
|
|
132
|
+
break;
|
|
133
|
+
case "APPLY":
|
|
134
|
+
opts.headers.set("Content-Type", SSA_CONTENT_TYPE);
|
|
135
|
+
opts.method = "PATCH";
|
|
136
|
+
url.searchParams.set("fieldManager", "pepr");
|
|
137
|
+
url.searchParams.set("fieldValidation", "Strict");
|
|
138
|
+
url.searchParams.set("force", applyCfg.force ? "true" : "false");
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
if (payload) {
|
|
142
|
+
opts.body = JSON.stringify(payload);
|
|
143
|
+
}
|
|
144
|
+
const resp = await (0, fetch_1.fetch)(url, opts);
|
|
145
|
+
if (resp.ok) {
|
|
146
|
+
return resp.data;
|
|
147
|
+
}
|
|
148
|
+
if (resp.status === 404 && method === "PATCH_STATUS") {
|
|
149
|
+
resp.statusText =
|
|
150
|
+
"Not Found" + " (NOTE: This error is expected if the resource has no status subresource)";
|
|
151
|
+
}
|
|
152
|
+
throw resp;
|
|
153
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../src/fluent/utils.test.ts"],"names":[],"mappings":""}
|