kubernetes-fluent-client 3.6.3 → 3.6.4
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/fluent/index.d.ts.map +1 -1
- package/dist/fluent/index.js +12 -9
- package/dist/fluent/utils.d.ts +30 -3
- package/dist/fluent/utils.d.ts.map +1 -1
- package/dist/fluent/utils.js +52 -29
- package/package.json +5 -5
- package/src/fluent/index.ts +16 -9
- package/src/fluent/utils.ts +71 -32
|
@@ -1 +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,aAAa,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAS,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAuC,MAAM,mBAAmB,CAAC;AAKjF;;;;;;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,
|
|
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,aAAa,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAS,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAuC,MAAM,mBAAmB,CAAC;AAKjF;;;;;;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,CAgSf"}
|
package/dist/fluent/index.js
CHANGED
|
@@ -92,7 +92,7 @@ export function K8s(model, filters = {}) {
|
|
|
92
92
|
throw new Error("Kind must be Pod or have a selector");
|
|
93
93
|
}
|
|
94
94
|
try {
|
|
95
|
-
const object = await k8sExec(model, filters, FetchMethods.GET);
|
|
95
|
+
const object = await k8sExec(model, filters, { method: FetchMethods.GET });
|
|
96
96
|
if (kind !== "Pod") {
|
|
97
97
|
if (kind === "Service") {
|
|
98
98
|
const svc = object;
|
|
@@ -118,7 +118,7 @@ export function K8s(model, filters = {}) {
|
|
|
118
118
|
throw new Error(`Failed to get logs in KFC Logs function`);
|
|
119
119
|
}
|
|
120
120
|
const podModel = { ...model, name: "V1Pod" };
|
|
121
|
-
const logPromises = podList.map(po => k8sExec(podModel, { ...filters, name: po.metadata.name }, FetchMethods.LOG));
|
|
121
|
+
const logPromises = podList.map(po => k8sExec(podModel, { ...filters, name: po.metadata.name }, { method: FetchMethods.LOG }));
|
|
122
122
|
const responses = await Promise.all(logPromises);
|
|
123
123
|
const combinedString = responses.reduce((accumulator, currentString, i) => {
|
|
124
124
|
const prefixedLines = currentString
|
|
@@ -142,7 +142,7 @@ export function K8s(model, filters = {}) {
|
|
|
142
142
|
}
|
|
143
143
|
filters.name = name;
|
|
144
144
|
}
|
|
145
|
-
return k8sExec(model, filters, FetchMethods.GET);
|
|
145
|
+
return k8sExec(model, filters, { method: FetchMethods.GET });
|
|
146
146
|
}
|
|
147
147
|
/**
|
|
148
148
|
* @inheritdoc
|
|
@@ -157,7 +157,7 @@ export function K8s(model, filters = {}) {
|
|
|
157
157
|
}
|
|
158
158
|
try {
|
|
159
159
|
// Try to delete the resource
|
|
160
|
-
await k8sExec(model, filters, FetchMethods.DELETE);
|
|
160
|
+
await k8sExec(model, filters, { method: FetchMethods.DELETE });
|
|
161
161
|
}
|
|
162
162
|
catch (e) {
|
|
163
163
|
// If the resource doesn't exist, ignore the error
|
|
@@ -173,7 +173,7 @@ export function K8s(model, filters = {}) {
|
|
|
173
173
|
*/
|
|
174
174
|
async function Apply(resource, applyCfg = { force: false }) {
|
|
175
175
|
syncFilters(resource);
|
|
176
|
-
return k8sExec(model, filters, FetchMethods.APPLY, resource, applyCfg);
|
|
176
|
+
return k8sExec(model, filters, { method: FetchMethods.APPLY, payload: resource }, applyCfg);
|
|
177
177
|
}
|
|
178
178
|
/**
|
|
179
179
|
* @inheritdoc
|
|
@@ -181,7 +181,7 @@ export function K8s(model, filters = {}) {
|
|
|
181
181
|
*/
|
|
182
182
|
async function Create(resource) {
|
|
183
183
|
syncFilters(resource);
|
|
184
|
-
return k8sExec(model, filters, FetchMethods.POST, resource);
|
|
184
|
+
return k8sExec(model, filters, { method: FetchMethods.POST, payload: resource });
|
|
185
185
|
}
|
|
186
186
|
/**
|
|
187
187
|
* @inheritdoc
|
|
@@ -204,7 +204,10 @@ export function K8s(model, filters = {}) {
|
|
|
204
204
|
},
|
|
205
205
|
};
|
|
206
206
|
// Try to evict the resource
|
|
207
|
-
await k8sExec(model, filters,
|
|
207
|
+
await k8sExec(model, filters, {
|
|
208
|
+
method: FetchMethods.POST,
|
|
209
|
+
payload: evictionPayload,
|
|
210
|
+
});
|
|
208
211
|
}
|
|
209
212
|
catch (e) {
|
|
210
213
|
// If the resource doesn't exist, ignore the error
|
|
@@ -223,7 +226,7 @@ export function K8s(model, filters = {}) {
|
|
|
223
226
|
if (payload.length < 1) {
|
|
224
227
|
throw new Error("No operations specified");
|
|
225
228
|
}
|
|
226
|
-
return k8sExec(model, filters, FetchMethods.PATCH, payload);
|
|
229
|
+
return k8sExec(model, filters, { method: FetchMethods.PATCH, payload });
|
|
227
230
|
}
|
|
228
231
|
/**
|
|
229
232
|
* @inheritdoc
|
|
@@ -231,7 +234,7 @@ export function K8s(model, filters = {}) {
|
|
|
231
234
|
*/
|
|
232
235
|
async function PatchStatus(resource) {
|
|
233
236
|
syncFilters(resource);
|
|
234
|
-
return k8sExec(model, filters, FetchMethods.PATCH_STATUS, resource);
|
|
237
|
+
return k8sExec(model, filters, { method: FetchMethods.PATCH_STATUS, payload: resource });
|
|
235
238
|
}
|
|
236
239
|
/**
|
|
237
240
|
* @inheritdoc
|
package/dist/fluent/utils.d.ts
CHANGED
|
@@ -45,16 +45,43 @@ export declare function pathBuilder<T extends GenericClass>(serverUrl: string, m
|
|
|
45
45
|
* @returns the fetch options and server URL
|
|
46
46
|
*/
|
|
47
47
|
export declare function k8sCfg(method: FetchMethods): K8sConfigPromise;
|
|
48
|
+
/**
|
|
49
|
+
* Prepares and mutates the request options and URL for Kubernetes PATCH or APPLY operations.
|
|
50
|
+
*
|
|
51
|
+
* This function modifies the request's HTTP method, headers, and URL based on the operation type.
|
|
52
|
+
* It handles the following:
|
|
53
|
+
*
|
|
54
|
+
* - `PATCH_STATUS`: Converts the method to `PATCH`, appends `/status` to the path, sets merge patch headers,
|
|
55
|
+
* and rewrites the payload to contain only the `status` field.
|
|
56
|
+
* - `PATCH`: Sets the content type to `application/json-patch+json`.
|
|
57
|
+
* - `APPLY`: Converts the method to `PATCH`, sets server-side apply headers, and updates the query string
|
|
58
|
+
* with field manager and force options.
|
|
59
|
+
*
|
|
60
|
+
* @template K
|
|
61
|
+
* @param methodPayload - The original method and payload. May be mutated if `PATCH_STATUS` is used.
|
|
62
|
+
* @param opts - The request options.
|
|
63
|
+
* @param opts.method - The HTTP method (e.g. `PATCH`, `APPLY`, or `PATCH_STATUS`).
|
|
64
|
+
* @param opts.headers - The headers to be updated with the correct content type.
|
|
65
|
+
* @param url - The URL to mutate with subresource path or query parameters.
|
|
66
|
+
* @param applyCfg - Server-side apply options, such as `force`.
|
|
67
|
+
*/
|
|
68
|
+
export declare function prepareRequestOptions<K>(methodPayload: MethodPayload<K>, opts: {
|
|
69
|
+
method?: string;
|
|
70
|
+
headers?: Record<string, string>;
|
|
71
|
+
}, url: URL, applyCfg: ApplyCfg): void;
|
|
72
|
+
export type MethodPayload<K> = {
|
|
73
|
+
method: FetchMethods;
|
|
74
|
+
payload?: K | unknown;
|
|
75
|
+
};
|
|
48
76
|
/**
|
|
49
77
|
* Execute a request against the Kubernetes API server.
|
|
50
78
|
*
|
|
51
79
|
* @param model - the model to use for the API
|
|
52
80
|
* @param filters - (optional) filter overrides, can also be chained
|
|
53
|
-
* @param
|
|
54
|
-
* @param payload - (optional) the payload to send
|
|
81
|
+
* @param methodPayload - method and payload for the request
|
|
55
82
|
* @param applyCfg - (optional) configuration for the apply method
|
|
56
83
|
*
|
|
57
84
|
* @returns the parsed JSON response
|
|
58
85
|
*/
|
|
59
|
-
export declare function k8sExec<T extends GenericClass, K>(model: T, filters: Filters,
|
|
86
|
+
export declare function k8sExec<T extends GenericClass, K>(model: T, filters: Filters, methodPayload: MethodPayload<K>, applyCfg?: ApplyCfg): Promise<K>;
|
|
60
87
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/fluent/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAS,UAAU,EAAE,MAAM,QAAQ,CAAC;AAI3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAMtF;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAkBvF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,CAqBvE;AACD;;;;GAIG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMvD;AACD;;;;;;;;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,GAAG,gBAAgB,CA+BnE;AASD
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/fluent/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAS,UAAU,EAAE,MAAM,QAAQ,CAAC;AAI3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAMtF;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAkBvF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,CAqBvE;AACD;;;;GAIG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMvD;AACD;;;;;;;;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,GAAG,gBAAgB,CA+BnE;AASD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,EAC/B,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,EAC3D,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,QAAQ,GACjB,IAAI,CAsBN;AAED,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC;CACvB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,EACrD,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,EAC/B,QAAQ,GAAE,QAA2B,cAkDtC"}
|
package/dist/fluent/utils.js
CHANGED
|
@@ -164,29 +164,70 @@ const isEvictionPayload = (payload) => payload !== null &&
|
|
|
164
164
|
typeof payload === "object" &&
|
|
165
165
|
"kind" in payload &&
|
|
166
166
|
payload.kind === "Eviction";
|
|
167
|
+
/**
|
|
168
|
+
* Prepares and mutates the request options and URL for Kubernetes PATCH or APPLY operations.
|
|
169
|
+
*
|
|
170
|
+
* This function modifies the request's HTTP method, headers, and URL based on the operation type.
|
|
171
|
+
* It handles the following:
|
|
172
|
+
*
|
|
173
|
+
* - `PATCH_STATUS`: Converts the method to `PATCH`, appends `/status` to the path, sets merge patch headers,
|
|
174
|
+
* and rewrites the payload to contain only the `status` field.
|
|
175
|
+
* - `PATCH`: Sets the content type to `application/json-patch+json`.
|
|
176
|
+
* - `APPLY`: Converts the method to `PATCH`, sets server-side apply headers, and updates the query string
|
|
177
|
+
* with field manager and force options.
|
|
178
|
+
*
|
|
179
|
+
* @template K
|
|
180
|
+
* @param methodPayload - The original method and payload. May be mutated if `PATCH_STATUS` is used.
|
|
181
|
+
* @param opts - The request options.
|
|
182
|
+
* @param opts.method - The HTTP method (e.g. `PATCH`, `APPLY`, or `PATCH_STATUS`).
|
|
183
|
+
* @param opts.headers - The headers to be updated with the correct content type.
|
|
184
|
+
* @param url - The URL to mutate with subresource path or query parameters.
|
|
185
|
+
* @param applyCfg - Server-side apply options, such as `force`.
|
|
186
|
+
*/
|
|
187
|
+
export function prepareRequestOptions(methodPayload, opts, url, applyCfg) {
|
|
188
|
+
switch (opts.method) {
|
|
189
|
+
// PATCH_STATUS is a special case that uses the PATCH method on status subresources
|
|
190
|
+
case "PATCH_STATUS":
|
|
191
|
+
opts.method = "PATCH";
|
|
192
|
+
url.pathname = `${url.pathname}/status`;
|
|
193
|
+
opts.headers["Content-Type"] = PatchStrategy.MergePatch;
|
|
194
|
+
methodPayload.payload = { status: methodPayload.payload.status };
|
|
195
|
+
break;
|
|
196
|
+
case "PATCH":
|
|
197
|
+
opts.headers["Content-Type"] = PatchStrategy.JsonPatch;
|
|
198
|
+
break;
|
|
199
|
+
case "APPLY":
|
|
200
|
+
opts.headers["Content-Type"] = SSA_CONTENT_TYPE;
|
|
201
|
+
opts.method = "PATCH";
|
|
202
|
+
url.searchParams.set("fieldManager", "pepr");
|
|
203
|
+
url.searchParams.set("fieldValidation", "Strict");
|
|
204
|
+
url.searchParams.set("force", applyCfg.force ? "true" : "false");
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
167
208
|
/**
|
|
168
209
|
* Execute a request against the Kubernetes API server.
|
|
169
210
|
*
|
|
170
211
|
* @param model - the model to use for the API
|
|
171
212
|
* @param filters - (optional) filter overrides, can also be chained
|
|
172
|
-
* @param
|
|
173
|
-
* @param payload - (optional) the payload to send
|
|
213
|
+
* @param methodPayload - method and payload for the request
|
|
174
214
|
* @param applyCfg - (optional) configuration for the apply method
|
|
175
215
|
*
|
|
176
216
|
* @returns the parsed JSON response
|
|
177
217
|
*/
|
|
178
|
-
export async function k8sExec(model, filters,
|
|
218
|
+
export async function k8sExec(model, filters, methodPayload, applyCfg = { force: false }) {
|
|
179
219
|
const reconstruct = async (method) => {
|
|
180
220
|
const configMethod = method === FetchMethods.LOG ? FetchMethods.GET : method;
|
|
181
221
|
const { opts, serverUrl } = await k8sCfg(configMethod);
|
|
182
222
|
// Build the base path once, using excludeName only for standard POST requests
|
|
183
|
-
const shouldExcludeName = method ===
|
|
223
|
+
const shouldExcludeName = method === FetchMethods.POST &&
|
|
224
|
+
!(methodPayload.payload && isEvictionPayload(methodPayload.payload));
|
|
184
225
|
const baseUrl = pathBuilder(serverUrl.toString(), model, filters, shouldExcludeName);
|
|
185
226
|
// Append appropriate subresource paths
|
|
186
|
-
if (payload && isEvictionPayload(payload)) {
|
|
227
|
+
if (methodPayload.payload && isEvictionPayload(methodPayload.payload)) {
|
|
187
228
|
baseUrl.pathname = `${baseUrl.pathname}/eviction`;
|
|
188
229
|
}
|
|
189
|
-
else if (method ===
|
|
230
|
+
else if (method === FetchMethods.LOG) {
|
|
190
231
|
baseUrl.pathname = `${baseUrl.pathname}/log`;
|
|
191
232
|
}
|
|
192
233
|
return {
|
|
@@ -194,35 +235,17 @@ export async function k8sExec(model, filters, method, payload, applyCfg = { forc
|
|
|
194
235
|
opts,
|
|
195
236
|
};
|
|
196
237
|
};
|
|
197
|
-
const { opts, serverUrl } = await reconstruct(method);
|
|
238
|
+
const { opts, serverUrl } = await reconstruct(methodPayload.method);
|
|
198
239
|
const url = serverUrl instanceof URL ? serverUrl : new URL(serverUrl);
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
opts.method = "PATCH";
|
|
203
|
-
url.pathname = `${url.pathname}/status`;
|
|
204
|
-
opts.headers["Content-Type"] = PatchStrategy.MergePatch;
|
|
205
|
-
payload = { status: payload.status };
|
|
206
|
-
break;
|
|
207
|
-
case "PATCH":
|
|
208
|
-
opts.headers["Content-Type"] = PatchStrategy.JsonPatch;
|
|
209
|
-
break;
|
|
210
|
-
case "APPLY":
|
|
211
|
-
opts.headers["Content-Type"] = SSA_CONTENT_TYPE;
|
|
212
|
-
opts.method = "PATCH";
|
|
213
|
-
url.searchParams.set("fieldManager", "pepr");
|
|
214
|
-
url.searchParams.set("fieldValidation", "Strict");
|
|
215
|
-
url.searchParams.set("force", applyCfg.force ? "true" : "false");
|
|
216
|
-
break;
|
|
217
|
-
}
|
|
218
|
-
if (payload) {
|
|
219
|
-
opts.body = JSON.stringify(payload);
|
|
240
|
+
prepareRequestOptions(methodPayload, opts, url, applyCfg);
|
|
241
|
+
if (methodPayload.payload) {
|
|
242
|
+
opts.body = JSON.stringify(methodPayload.payload);
|
|
220
243
|
}
|
|
221
244
|
const resp = await fetch(url, opts);
|
|
222
245
|
if (resp.ok) {
|
|
223
246
|
return resp.data;
|
|
224
247
|
}
|
|
225
|
-
if (resp.status === 404 && method ===
|
|
248
|
+
if (resp.status === 404 && methodPayload.method === FetchMethods.PATCH_STATUS) {
|
|
226
249
|
resp.statusText =
|
|
227
250
|
"Not Found" + " (NOTE: This error is expected if the resource has no status subresource)";
|
|
228
251
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kubernetes-fluent-client",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.4",
|
|
4
4
|
"description": "A @kubernetes/client-node fluent API wrapper that leverages K8s Server Side Apply.",
|
|
5
5
|
"bin": "./dist/cli.js",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -70,15 +70,15 @@
|
|
|
70
70
|
"@types/urijs": "^1.19.25",
|
|
71
71
|
"@types/ws": "^8.18.1",
|
|
72
72
|
"@types/yargs": "17.0.33",
|
|
73
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
74
|
-
"@typescript-eslint/parser": "8.
|
|
73
|
+
"@typescript-eslint/eslint-plugin": "8.34.1",
|
|
74
|
+
"@typescript-eslint/parser": "8.34.1",
|
|
75
75
|
"@vitest/coverage-v8": "^3.2.1",
|
|
76
76
|
"command-line-args": "^6.0.1",
|
|
77
|
-
"eslint-plugin-jsdoc": "
|
|
77
|
+
"eslint-plugin-jsdoc": "51.2.1",
|
|
78
78
|
"globals": "^16.0.0",
|
|
79
79
|
"husky": "^9.1.6",
|
|
80
80
|
"lint-staged": "^16.0.0",
|
|
81
|
-
"prettier": "3.
|
|
81
|
+
"prettier": "3.6.0",
|
|
82
82
|
"semantic-release": "24.2.5",
|
|
83
83
|
"typescript": "5.8.3",
|
|
84
84
|
"vitest": "^3.2.1"
|
package/src/fluent/index.ts
CHANGED
|
@@ -115,7 +115,7 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
try {
|
|
118
|
-
const object = await k8sExec<T, K>(model, filters, FetchMethods.GET);
|
|
118
|
+
const object = await k8sExec<T, K>(model, filters, { method: FetchMethods.GET });
|
|
119
119
|
|
|
120
120
|
if (kind !== "Pod") {
|
|
121
121
|
if (kind === "Service") {
|
|
@@ -145,7 +145,11 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
145
145
|
|
|
146
146
|
const podModel = { ...model, name: "V1Pod" };
|
|
147
147
|
const logPromises = podList.map(po =>
|
|
148
|
-
k8sExec<T, string>(
|
|
148
|
+
k8sExec<T, string>(
|
|
149
|
+
podModel,
|
|
150
|
+
{ ...filters, name: po.metadata!.name! },
|
|
151
|
+
{ method: FetchMethods.LOG },
|
|
152
|
+
),
|
|
149
153
|
);
|
|
150
154
|
|
|
151
155
|
const responses = await Promise.all(logPromises);
|
|
@@ -180,7 +184,7 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
180
184
|
filters.name = name;
|
|
181
185
|
}
|
|
182
186
|
|
|
183
|
-
return k8sExec<T, K | KubernetesListObject<K>>(model, filters, FetchMethods.GET);
|
|
187
|
+
return k8sExec<T, K | KubernetesListObject<K>>(model, filters, { method: FetchMethods.GET });
|
|
184
188
|
}
|
|
185
189
|
|
|
186
190
|
/**
|
|
@@ -196,7 +200,7 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
196
200
|
|
|
197
201
|
try {
|
|
198
202
|
// Try to delete the resource
|
|
199
|
-
await k8sExec<T, void>(model, filters, FetchMethods.DELETE);
|
|
203
|
+
await k8sExec<T, void>(model, filters, { method: FetchMethods.DELETE });
|
|
200
204
|
} catch (e) {
|
|
201
205
|
// If the resource doesn't exist, ignore the error
|
|
202
206
|
if (e.status === StatusCodes.NOT_FOUND) {
|
|
@@ -216,7 +220,7 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
216
220
|
applyCfg: ApplyCfg = { force: false },
|
|
217
221
|
): Promise<K> {
|
|
218
222
|
syncFilters(resource as K);
|
|
219
|
-
return k8sExec(model, filters, FetchMethods.APPLY, resource, applyCfg);
|
|
223
|
+
return k8sExec(model, filters, { method: FetchMethods.APPLY, payload: resource }, applyCfg);
|
|
220
224
|
}
|
|
221
225
|
|
|
222
226
|
/**
|
|
@@ -225,7 +229,7 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
225
229
|
*/
|
|
226
230
|
async function Create(resource: K): Promise<K> {
|
|
227
231
|
syncFilters(resource);
|
|
228
|
-
return k8sExec(model, filters, FetchMethods.POST, resource);
|
|
232
|
+
return k8sExec(model, filters, { method: FetchMethods.POST, payload: resource });
|
|
229
233
|
}
|
|
230
234
|
|
|
231
235
|
/**
|
|
@@ -249,7 +253,10 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
249
253
|
},
|
|
250
254
|
};
|
|
251
255
|
// Try to evict the resource
|
|
252
|
-
await k8sExec<T, void>(model, filters,
|
|
256
|
+
await k8sExec<T, void>(model, filters, {
|
|
257
|
+
method: FetchMethods.POST,
|
|
258
|
+
payload: evictionPayload,
|
|
259
|
+
});
|
|
253
260
|
} catch (e) {
|
|
254
261
|
// If the resource doesn't exist, ignore the error
|
|
255
262
|
if (e.status === StatusCodes.NOT_FOUND) {
|
|
@@ -269,7 +276,7 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
269
276
|
throw new Error("No operations specified");
|
|
270
277
|
}
|
|
271
278
|
|
|
272
|
-
return k8sExec(model, filters, FetchMethods.PATCH, payload);
|
|
279
|
+
return k8sExec(model, filters, { method: FetchMethods.PATCH, payload });
|
|
273
280
|
}
|
|
274
281
|
|
|
275
282
|
/**
|
|
@@ -278,7 +285,7 @@ export function K8s<T extends GenericClass, K extends KubernetesObject = Instanc
|
|
|
278
285
|
*/
|
|
279
286
|
async function PatchStatus(resource: PartialDeep<K>): Promise<K> {
|
|
280
287
|
syncFilters(resource as K);
|
|
281
|
-
return k8sExec(model, filters, FetchMethods.PATCH_STATUS, resource);
|
|
288
|
+
return k8sExec(model, filters, { method: FetchMethods.PATCH_STATUS, payload: resource });
|
|
282
289
|
}
|
|
283
290
|
|
|
284
291
|
/**
|
package/src/fluent/utils.ts
CHANGED
|
@@ -203,13 +203,66 @@ const isEvictionPayload = (payload: unknown): payload is Eviction =>
|
|
|
203
203
|
"kind" in payload &&
|
|
204
204
|
(payload as { kind: string }).kind === "Eviction";
|
|
205
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Prepares and mutates the request options and URL for Kubernetes PATCH or APPLY operations.
|
|
208
|
+
*
|
|
209
|
+
* This function modifies the request's HTTP method, headers, and URL based on the operation type.
|
|
210
|
+
* It handles the following:
|
|
211
|
+
*
|
|
212
|
+
* - `PATCH_STATUS`: Converts the method to `PATCH`, appends `/status` to the path, sets merge patch headers,
|
|
213
|
+
* and rewrites the payload to contain only the `status` field.
|
|
214
|
+
* - `PATCH`: Sets the content type to `application/json-patch+json`.
|
|
215
|
+
* - `APPLY`: Converts the method to `PATCH`, sets server-side apply headers, and updates the query string
|
|
216
|
+
* with field manager and force options.
|
|
217
|
+
*
|
|
218
|
+
* @template K
|
|
219
|
+
* @param methodPayload - The original method and payload. May be mutated if `PATCH_STATUS` is used.
|
|
220
|
+
* @param opts - The request options.
|
|
221
|
+
* @param opts.method - The HTTP method (e.g. `PATCH`, `APPLY`, or `PATCH_STATUS`).
|
|
222
|
+
* @param opts.headers - The headers to be updated with the correct content type.
|
|
223
|
+
* @param url - The URL to mutate with subresource path or query parameters.
|
|
224
|
+
* @param applyCfg - Server-side apply options, such as `force`.
|
|
225
|
+
*/
|
|
226
|
+
export function prepareRequestOptions<K>(
|
|
227
|
+
methodPayload: MethodPayload<K>,
|
|
228
|
+
opts: { method?: string; headers?: Record<string, string> },
|
|
229
|
+
url: URL,
|
|
230
|
+
applyCfg: ApplyCfg,
|
|
231
|
+
): void {
|
|
232
|
+
switch (opts.method) {
|
|
233
|
+
// PATCH_STATUS is a special case that uses the PATCH method on status subresources
|
|
234
|
+
case "PATCH_STATUS":
|
|
235
|
+
opts.method = "PATCH";
|
|
236
|
+
url.pathname = `${url.pathname}/status`;
|
|
237
|
+
(opts.headers as Record<string, string>)["Content-Type"] = PatchStrategy.MergePatch;
|
|
238
|
+
methodPayload.payload = { status: (methodPayload.payload as { status: unknown }).status };
|
|
239
|
+
break;
|
|
240
|
+
|
|
241
|
+
case "PATCH":
|
|
242
|
+
(opts.headers as Record<string, string>)["Content-Type"] = PatchStrategy.JsonPatch;
|
|
243
|
+
break;
|
|
244
|
+
|
|
245
|
+
case "APPLY":
|
|
246
|
+
(opts.headers as Record<string, string>)["Content-Type"] = SSA_CONTENT_TYPE;
|
|
247
|
+
opts.method = "PATCH";
|
|
248
|
+
url.searchParams.set("fieldManager", "pepr");
|
|
249
|
+
url.searchParams.set("fieldValidation", "Strict");
|
|
250
|
+
url.searchParams.set("force", applyCfg.force ? "true" : "false");
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export type MethodPayload<K> = {
|
|
256
|
+
method: FetchMethods;
|
|
257
|
+
payload?: K | unknown;
|
|
258
|
+
};
|
|
259
|
+
|
|
206
260
|
/**
|
|
207
261
|
* Execute a request against the Kubernetes API server.
|
|
208
262
|
*
|
|
209
263
|
* @param model - the model to use for the API
|
|
210
264
|
* @param filters - (optional) filter overrides, can also be chained
|
|
211
|
-
* @param
|
|
212
|
-
* @param payload - (optional) the payload to send
|
|
265
|
+
* @param methodPayload - method and payload for the request
|
|
213
266
|
* @param applyCfg - (optional) configuration for the apply method
|
|
214
267
|
*
|
|
215
268
|
* @returns the parsed JSON response
|
|
@@ -217,8 +270,7 @@ const isEvictionPayload = (payload: unknown): payload is Eviction =>
|
|
|
217
270
|
export async function k8sExec<T extends GenericClass, K>(
|
|
218
271
|
model: T,
|
|
219
272
|
filters: Filters,
|
|
220
|
-
|
|
221
|
-
payload?: K | unknown,
|
|
273
|
+
methodPayload: MethodPayload<K>,
|
|
222
274
|
applyCfg: ApplyCfg = { force: false },
|
|
223
275
|
) {
|
|
224
276
|
const reconstruct = async (method: FetchMethods): K8sConfigPromise => {
|
|
@@ -226,13 +278,15 @@ export async function k8sExec<T extends GenericClass, K>(
|
|
|
226
278
|
const { opts, serverUrl } = await k8sCfg(configMethod);
|
|
227
279
|
|
|
228
280
|
// Build the base path once, using excludeName only for standard POST requests
|
|
229
|
-
const shouldExcludeName =
|
|
281
|
+
const shouldExcludeName =
|
|
282
|
+
method === FetchMethods.POST &&
|
|
283
|
+
!(methodPayload.payload && isEvictionPayload(methodPayload.payload));
|
|
230
284
|
const baseUrl = pathBuilder(serverUrl.toString(), model, filters, shouldExcludeName);
|
|
231
285
|
|
|
232
286
|
// Append appropriate subresource paths
|
|
233
|
-
if (payload && isEvictionPayload(payload)) {
|
|
287
|
+
if (methodPayload.payload && isEvictionPayload(methodPayload.payload)) {
|
|
234
288
|
baseUrl.pathname = `${baseUrl.pathname}/eviction`;
|
|
235
|
-
} else if (method ===
|
|
289
|
+
} else if (method === FetchMethods.LOG) {
|
|
236
290
|
baseUrl.pathname = `${baseUrl.pathname}/log`;
|
|
237
291
|
}
|
|
238
292
|
|
|
@@ -242,33 +296,18 @@ export async function k8sExec<T extends GenericClass, K>(
|
|
|
242
296
|
};
|
|
243
297
|
};
|
|
244
298
|
|
|
245
|
-
const { opts, serverUrl } = await reconstruct(method);
|
|
299
|
+
const { opts, serverUrl } = await reconstruct(methodPayload.method);
|
|
246
300
|
const url: URL = serverUrl instanceof URL ? serverUrl : new URL(serverUrl);
|
|
247
301
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
payload = { status: (payload as { status: unknown }).status };
|
|
255
|
-
break;
|
|
256
|
-
|
|
257
|
-
case "PATCH":
|
|
258
|
-
(opts.headers as Record<string, string>)["Content-Type"] = PatchStrategy.JsonPatch;
|
|
259
|
-
break;
|
|
260
|
-
|
|
261
|
-
case "APPLY":
|
|
262
|
-
(opts.headers as Record<string, string>)["Content-Type"] = SSA_CONTENT_TYPE;
|
|
263
|
-
opts.method = "PATCH";
|
|
264
|
-
url.searchParams.set("fieldManager", "pepr");
|
|
265
|
-
url.searchParams.set("fieldValidation", "Strict");
|
|
266
|
-
url.searchParams.set("force", applyCfg.force ? "true" : "false");
|
|
267
|
-
break;
|
|
268
|
-
}
|
|
302
|
+
prepareRequestOptions(
|
|
303
|
+
methodPayload,
|
|
304
|
+
opts as { method?: string; headers?: Record<string, string> },
|
|
305
|
+
url,
|
|
306
|
+
applyCfg,
|
|
307
|
+
);
|
|
269
308
|
|
|
270
|
-
if (payload) {
|
|
271
|
-
opts.body = JSON.stringify(payload);
|
|
309
|
+
if (methodPayload.payload) {
|
|
310
|
+
opts.body = JSON.stringify(methodPayload.payload);
|
|
272
311
|
}
|
|
273
312
|
const resp = await fetch<K>(url, opts);
|
|
274
313
|
|
|
@@ -276,7 +315,7 @@ export async function k8sExec<T extends GenericClass, K>(
|
|
|
276
315
|
return resp.data;
|
|
277
316
|
}
|
|
278
317
|
|
|
279
|
-
if (resp.status === 404 && method ===
|
|
318
|
+
if (resp.status === 404 && methodPayload.method === FetchMethods.PATCH_STATUS) {
|
|
280
319
|
resp.statusText =
|
|
281
320
|
"Not Found" + " (NOTE: This error is expected if the resource has no status subresource)";
|
|
282
321
|
}
|