openk8s 1.0.1 → 1.0.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/package.json +5 -2
- package/src/app/__tests__/app-state.test.ts +376 -0
- package/src/app/__tests__/components/inspector-tokens.test.ts +101 -0
- package/src/app/__tests__/utils.test.ts +358 -0
- package/src/app/app-actions.ts +262 -0
- package/src/app/app-state.ts +4 -262
- package/src/app/app.tsx +22 -170
- package/src/app/components/detail-sections.tsx +131 -0
- package/src/app/components/footer.tsx +52 -0
- package/src/app/components/header.tsx +37 -0
- package/src/app/components/inspector-tokens.ts +93 -0
- package/src/app/components/inspector.tsx +3 -239
- package/src/app/components/resource-rows.tsx +5 -0
- package/src/app/hooks/keyboard/filter-handlers.ts +40 -0
- package/src/app/hooks/keyboard/global-handlers.ts +134 -0
- package/src/app/hooks/keyboard/helm-handlers.ts +104 -0
- package/src/app/hooks/keyboard/logs-handlers.ts +80 -0
- package/src/app/hooks/keyboard/navigation-handlers.ts +103 -0
- package/src/app/hooks/keyboard/overlay-handlers.ts +138 -0
- package/src/app/hooks/keyboard/port-forward-handlers.ts +71 -0
- package/src/app/hooks/keyboard/shell-edit-handlers.ts +253 -0
- package/src/app/hooks/use-app-keyboard.ts +56 -621
- package/src/app/hooks/use-app-side-effects.ts +1 -1
- package/src/app/hooks/use-clipboard.ts +1 -1
- package/src/app/hooks/use-data-fetching.ts +2 -9
- package/src/app/hooks/use-log-stream.ts +1 -1
- package/src/app/hooks/use-port-forward.ts +1 -1
- package/src/app/use-footer-hints.ts +107 -0
- package/src/index.tsx +4 -0
- package/src/lib/k8s/__tests__/k8s-format.test.ts +42 -0
- package/src/lib/k8s/__tests__/resource-detail-builder.test.ts +215 -0
- package/src/lib/k8s/__tests__/resource-parser.test.ts +455 -0
- package/src/lib/k8s/detail-builders/event-builder.ts +21 -0
- package/src/lib/k8s/detail-builders/hpa-cronjob-builder.ts +63 -0
- package/src/lib/k8s/detail-builders/node-builder.ts +41 -0
- package/src/lib/k8s/detail-builders/overview-builder.ts +103 -0
- package/src/lib/k8s/detail-builders/pod-builder.ts +140 -0
- package/src/lib/k8s/detail-builders/rbac-builder.ts +57 -0
- package/src/lib/k8s/resource-detail-builder.ts +22 -502
- package/src/lib/kubectl/__tests__/kubectl-helpers.test.ts +343 -0
- package/src/lib/kubectl/__tests__/metrics-utils.test.ts +84 -0
- package/src/lib/kubectl/__tests__/spawn-utils.test.ts +56 -0
- package/src/lib/kubectl/kubectl-helpers.ts +246 -0
- package/src/lib/kubectl/kubectl-service.ts +77 -565
- package/src/lib/kubectl/kubectl-types.ts +248 -0
- package/src/lib/kubectl/metrics-utils.ts +33 -0
- package/src/lib/kubectl/spawn-utils.ts +27 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { describe, expect, test, spyOn } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
loadError,
|
|
4
|
+
statusLine,
|
|
5
|
+
deleteStatusMessage,
|
|
6
|
+
resourceDetailText,
|
|
7
|
+
activePortForwardRoute,
|
|
8
|
+
activePortForwardLabel,
|
|
9
|
+
portForwardId,
|
|
10
|
+
parseLocalPort,
|
|
11
|
+
statusTone,
|
|
12
|
+
kindDescription,
|
|
13
|
+
currentKindLabel,
|
|
14
|
+
resourcePreview,
|
|
15
|
+
normalizeFilter,
|
|
16
|
+
filterResources,
|
|
17
|
+
nextVisibleResourceName,
|
|
18
|
+
defaultNamespace,
|
|
19
|
+
selectedRef,
|
|
20
|
+
selectedForwardsForRef,
|
|
21
|
+
} from "../utils";
|
|
22
|
+
import type { ResourceListItem, ActivePortForward, ResourceDetail, NamespaceItem, ResourceKind } from "../../lib/k8s/types";
|
|
23
|
+
|
|
24
|
+
// ── loadError ────────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
describe("loadError", () => {
|
|
27
|
+
test("formats Error instance", () => {
|
|
28
|
+
const result = loadError(new Error("Something failed"));
|
|
29
|
+
expect(result.message).toBe("Something failed");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("includes error cause", () => {
|
|
33
|
+
const error = new Error("Failed to connect", { cause: "Connection refused" });
|
|
34
|
+
const result = loadError(error);
|
|
35
|
+
expect(result.message).toBe("Failed to connect");
|
|
36
|
+
expect(result.detail).toBe("Connection refused");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("returns generic message for non-Error", () => {
|
|
40
|
+
expect(loadError("string error").message).toBe("Unexpected error");
|
|
41
|
+
expect(loadError(42).message).toBe("Unexpected error");
|
|
42
|
+
expect(loadError(null).message).toBe("Unexpected error");
|
|
43
|
+
expect(loadError(undefined).message).toBe("Unexpected error");
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// ── statusLine ───────────────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
describe("statusLine", () => {
|
|
50
|
+
test("formats with namespace", () => {
|
|
51
|
+
expect(statusLine({ ref: { kind: "Pod", name: "nginx", namespace: "default" } })).toBe("Pod default/nginx");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("formats without namespace", () => {
|
|
55
|
+
expect(statusLine({ ref: { kind: "Node", name: "node-1" } })).toBe("Node node-1");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("returns fallback for undefined ref", () => {
|
|
59
|
+
expect(statusLine({})).toBe("No selection");
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// ── deleteStatusMessage ──────────────────────────────────────────────────────
|
|
64
|
+
|
|
65
|
+
describe("deleteStatusMessage", () => {
|
|
66
|
+
test("single target", () => {
|
|
67
|
+
expect(deleteStatusMessage([{ kind: "Pod", name: "web" }], "Deleting")).toBe("Deleting Pod web");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("multiple targets", () => {
|
|
71
|
+
expect(deleteStatusMessage([{ kind: "Pod", name: "a" }, { kind: "Pod", name: "b" }], "Deleted")).toBe("Deleted 2 resources");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("empty targets", () => {
|
|
75
|
+
expect(deleteStatusMessage([], "Deleting")).toBe("Deleting no selection");
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// ── resourceDetailText ───────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
describe("resourceDetailText", () => {
|
|
82
|
+
test("plain string line", () => {
|
|
83
|
+
const result = resourceDetailText("kind: Pod", []);
|
|
84
|
+
expect(result).toEqual({ id: "kind: Pod", text: "kind: Pod", revealable: false });
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("non-revealable structured line", () => {
|
|
88
|
+
const line = { id: "l1", text: "KEY=value" };
|
|
89
|
+
const result = resourceDetailText(line, ["l1"]);
|
|
90
|
+
expect(result).toEqual({ id: "l1", text: "KEY=value", revealable: false });
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("revealable line when not revealed", () => {
|
|
94
|
+
const line = { id: "l1", text: "KEY=*****", revealedText: "KEY=secret", revealable: true };
|
|
95
|
+
const result = resourceDetailText(line, []);
|
|
96
|
+
expect(result.text).toContain("[click to reveal]");
|
|
97
|
+
expect(result.revealable).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("revealable line when revealed", () => {
|
|
101
|
+
const line = { id: "l1", text: "KEY=*****", revealedText: "KEY=secret", revealable: true };
|
|
102
|
+
const result = resourceDetailText(line, ["l1"]);
|
|
103
|
+
expect(result.text).toBe("KEY=secret");
|
|
104
|
+
expect(result.revealable).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ── Port forward helpers ────────────────────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
describe("activePortForwardRoute", () => {
|
|
111
|
+
test("formats route", () => {
|
|
112
|
+
const pf: ActivePortForward = {
|
|
113
|
+
id: "pf1", context: "prod", namespace: "default", namespaced: true,
|
|
114
|
+
ref: { kind: "Pod", name: "web" }, localPort: 8080, remotePort: 80, status: "ready",
|
|
115
|
+
};
|
|
116
|
+
expect(activePortForwardRoute(pf)).toBe("localhost:8080 -> 80");
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe("activePortForwardLabel", () => {
|
|
121
|
+
test("formats full label", () => {
|
|
122
|
+
const pf: ActivePortForward = {
|
|
123
|
+
id: "pf1", context: "prod", namespace: "default", namespaced: true,
|
|
124
|
+
ref: { kind: "Pod", name: "web", namespace: "default" }, localPort: 8080, remotePort: 80, status: "ready",
|
|
125
|
+
};
|
|
126
|
+
expect(activePortForwardLabel(pf)).toBe("Pod default/web localhost:8080 -> 80");
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe("portForwardId", () => {
|
|
131
|
+
test("generates unique ID", () => {
|
|
132
|
+
expect(portForwardId({ context: "prod", namespace: "default", ref: { kind: "Pod", name: "web" }, localPort: 8080, remotePort: 80 }))
|
|
133
|
+
.toBe("prod:default:Pod:web:8080:80");
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// ── parseLocalPort ──────────────────────────────────────────────────────────
|
|
138
|
+
|
|
139
|
+
describe("parseLocalPort", () => {
|
|
140
|
+
test("parses valid port", () => expect(parseLocalPort("8080")).toBe(8080));
|
|
141
|
+
test("rejects non-numeric", () => expect(parseLocalPort("abc")).toBeUndefined());
|
|
142
|
+
test("rejects out of range", () => expect(parseLocalPort("99999")).toBeUndefined());
|
|
143
|
+
test("rejects zero", () => expect(parseLocalPort("0")).toBeUndefined());
|
|
144
|
+
test("rejects negative", () => expect(parseLocalPort("-1")).toBeUndefined());
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ── statusTone ──────────────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
describe("statusTone", () => {
|
|
150
|
+
test("danger keywords", () => {
|
|
151
|
+
expect(statusTone("Error")).toBe("danger");
|
|
152
|
+
expect(statusTone("CrashLoopBackOff")).toBe("danger");
|
|
153
|
+
expect(statusTone("NotReady")).toBe("danger");
|
|
154
|
+
expect(statusTone("Evicted")).toBe("danger");
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("warning keywords", () => {
|
|
158
|
+
expect(statusTone("Pending")).toBe("warning");
|
|
159
|
+
expect(statusTone("Warning")).toBe("warning");
|
|
160
|
+
expect(statusTone("MemoryPressure")).toBe("warning");
|
|
161
|
+
expect(statusTone("Terminating")).toBe("warning");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("success keywords", () => {
|
|
165
|
+
expect(statusTone("Running")).toBe("success");
|
|
166
|
+
expect(statusTone("Ready")).toBe("success");
|
|
167
|
+
expect(statusTone("Succeeded")).toBe("success");
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("neutral fallback", () => {
|
|
171
|
+
expect(statusTone("Unknown")).toBe("info");
|
|
172
|
+
expect(statusTone("Scaling")).toBe("info");
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// ── kindDescription ─────────────────────────────────────────────────────────
|
|
177
|
+
|
|
178
|
+
describe("kindDescription", () => {
|
|
179
|
+
test("namespaced without short names", () => {
|
|
180
|
+
expect(kindDescription({ name: "pods", namespaced: true, shortNames: [] })).toBe("Namespaced");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test("cluster-scoped with short names", () => {
|
|
184
|
+
expect(kindDescription({ name: "nodes", namespaced: false, shortNames: ["no"] })).toBe("Cluster no");
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// ── currentKindLabel ─────────────────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
describe("currentKindLabel", () => {
|
|
191
|
+
test("finds kind by name", () => {
|
|
192
|
+
const kinds: ResourceKind[] = [{ name: "pods", namespaced: true, shortNames: ["po"] }];
|
|
193
|
+
expect(currentKindLabel({ resourceKinds: kinds, selectedKind: "pods" })).toBe("pods");
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test("falls back to selected kind string", () => {
|
|
197
|
+
expect(currentKindLabel({ resourceKinds: [], selectedKind: "pods" })).toBe("pods");
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// ── resourcePreview ──────────────────────────────────────────────────────────
|
|
202
|
+
|
|
203
|
+
describe("resourcePreview", () => {
|
|
204
|
+
test("fallback when no resource", () => {
|
|
205
|
+
expect(resourcePreview({}))?.toEqual(["Select a resource to inspect it."]);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test("preview with resource", () => {
|
|
209
|
+
const resource: ResourceListItem = {
|
|
210
|
+
ref: { kind: "Pod", name: "web", namespace: "default" },
|
|
211
|
+
status: "Running", age: "5m", summary: "nginx",
|
|
212
|
+
};
|
|
213
|
+
const lines = resourcePreview({ resource });
|
|
214
|
+
expect(lines).toContain("kind: Pod");
|
|
215
|
+
expect(lines).toContain("name: web");
|
|
216
|
+
expect(lines).toContain("summary: nginx");
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// ── normalizeFilter ─────────────────────────────────────────────────────────
|
|
221
|
+
|
|
222
|
+
describe("normalizeFilter", () => {
|
|
223
|
+
test("trims and lowercases", () => {
|
|
224
|
+
expect(normalizeFilter(" Nginx ")).toBe("nginx");
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// ── filterResources ─────────────────────────────────────────────────────────
|
|
229
|
+
|
|
230
|
+
describe("filterResources", () => {
|
|
231
|
+
const resources: ResourceListItem[] = [
|
|
232
|
+
{ ref: { kind: "Pod", name: "nginx-abc" }, status: "Running", age: "5m", summary: "nginx web server" },
|
|
233
|
+
{ ref: { kind: "Pod", name: "redis-cache" }, status: "Running", age: "2m", summary: "redis cache" },
|
|
234
|
+
{ ref: { kind: "Pod", name: "mysql-db" }, status: "Pending", age: "1m", summary: "mysql database" },
|
|
235
|
+
];
|
|
236
|
+
|
|
237
|
+
test("returns all resources when filter is empty", () => {
|
|
238
|
+
expect(filterResources({ resources, filter: "" })).toHaveLength(3);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("filters by name", () => {
|
|
242
|
+
expect(filterResources({ resources, filter: "nginx" })).toHaveLength(1);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test("filters by status", () => {
|
|
246
|
+
expect(filterResources({ resources, filter: "Pending" })).toHaveLength(1);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test("filters by summary", () => {
|
|
250
|
+
expect(filterResources({ resources, filter: "cache" })).toHaveLength(1);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test("is case-insensitive", () => {
|
|
254
|
+
expect(filterResources({ resources, filter: "NGINX" })).toHaveLength(1);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test("returns empty for no match", () => {
|
|
258
|
+
expect(filterResources({ resources, filter: "zzzzz" })).toHaveLength(0);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// ── nextVisibleResourceName ─────────────────────────────────────────────────
|
|
263
|
+
|
|
264
|
+
describe("nextVisibleResourceName", () => {
|
|
265
|
+
const resources: ResourceListItem[] = [
|
|
266
|
+
{ ref: { kind: "Pod", name: "a" }, status: "Running", age: "1m", summary: "" },
|
|
267
|
+
{ ref: { kind: "Pod", name: "b" }, status: "Running", age: "2m", summary: "" },
|
|
268
|
+
];
|
|
269
|
+
|
|
270
|
+
test("returns undefined for empty list", () => {
|
|
271
|
+
expect(nextVisibleResourceName({ resources: [], selectedName: "a" })).toBeUndefined();
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test("returns selected name when it exists", () => {
|
|
275
|
+
expect(nextVisibleResourceName({ resources, selectedName: "a" })).toBe("a");
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test("returns first when selected name not present", () => {
|
|
279
|
+
expect(nextVisibleResourceName({ resources, selectedName: "c" })).toBe("a");
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
test("returns first when no selection", () => {
|
|
283
|
+
expect(nextVisibleResourceName({ resources, selectedName: undefined })).toBe("a");
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// ── defaultNamespace ─────────────────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
describe("defaultNamespace", () => {
|
|
290
|
+
const namespaces: NamespaceItem[] = [
|
|
291
|
+
{ name: "default" },
|
|
292
|
+
{ name: "kube-system" },
|
|
293
|
+
];
|
|
294
|
+
|
|
295
|
+
test("keeps current namespace if it exists", () => {
|
|
296
|
+
expect(defaultNamespace({ namespaces, currentNamespace: "kube-system" })).toBe("kube-system");
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
test("returns first namespace when current not found", () => {
|
|
300
|
+
expect(defaultNamespace({ namespaces, currentNamespace: "missing" })).toBe("default");
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test("returns 'default' when no namespaces", () => {
|
|
304
|
+
expect(defaultNamespace({ namespaces: [], currentNamespace: "kube-system" })).toBe("default");
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// ── selectedRef ─────────────────────────────────────────────────────────────
|
|
309
|
+
|
|
310
|
+
describe("selectedRef", () => {
|
|
311
|
+
const detail: ResourceDetail = {
|
|
312
|
+
ref: { kind: "Pod", name: "web", namespace: "default" },
|
|
313
|
+
summaryLines: [], summarySections: [], yaml: "",
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
test("returns detail ref when it matches resource", () => {
|
|
317
|
+
const resource: ResourceListItem = { ref: { kind: "Pod", name: "web", namespace: "default" }, status: "Running", age: "1m", summary: "" };
|
|
318
|
+
expect(selectedRef({ detail, resource })).toBe(detail.ref);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
test("returns resource ref when detail doesn't match", () => {
|
|
322
|
+
const resource: ResourceListItem = { ref: { kind: "Pod", name: "other" }, status: "Running", age: "1m", summary: "" };
|
|
323
|
+
expect(selectedRef({ detail, resource })).toBe(resource.ref);
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
test("returns resource ref when no detail", () => {
|
|
327
|
+
const resource: ResourceListItem = { ref: { kind: "Pod", name: "web" }, status: "Running", age: "1m", summary: "" };
|
|
328
|
+
expect(selectedRef({ detail: undefined, resource })).toBe(resource.ref);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
test("returns undefined when neither", () => {
|
|
332
|
+
expect(selectedRef({})).toBeUndefined();
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// ── selectedForwardsForRef ──────────────────────────────────────────────────
|
|
337
|
+
|
|
338
|
+
describe("selectedForwardsForRef", () => {
|
|
339
|
+
const ref = { kind: "Pod", name: "web", namespace: "default" };
|
|
340
|
+
const forwards: ActivePortForward[] = [
|
|
341
|
+
{ id: "1", context: "p", namespace: "default", namespaced: true, ref, localPort: 8080, remotePort: 80, status: "ready" },
|
|
342
|
+
{ id: "2", context: "p", namespace: "default", namespaced: true, ref: { kind: "Pod", name: "db" }, localPort: 3306, remotePort: 3306, status: "ready" },
|
|
343
|
+
];
|
|
344
|
+
|
|
345
|
+
test("filters forwards matching the ref", () => {
|
|
346
|
+
const result = selectedForwardsForRef({ forwards, ref });
|
|
347
|
+
expect(result).toHaveLength(1);
|
|
348
|
+
expect(result[0]?.id).toBe("1");
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test("returns empty for undefined ref", () => {
|
|
352
|
+
expect(selectedForwardsForRef({ forwards, ref: undefined })).toEqual([]);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
test("returns empty when no forwards match", () => {
|
|
356
|
+
expect(selectedForwardsForRef({ forwards, ref: { kind: "Node", name: "n1" } })).toEqual([]);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ActivePortForward,
|
|
3
|
+
AppError,
|
|
4
|
+
AppState,
|
|
5
|
+
EventItem,
|
|
6
|
+
LoadStatus,
|
|
7
|
+
LogOptions,
|
|
8
|
+
Notification,
|
|
9
|
+
OverlayId,
|
|
10
|
+
PaneId,
|
|
11
|
+
ResourceDetail,
|
|
12
|
+
ResourceKind,
|
|
13
|
+
ResourceListItem,
|
|
14
|
+
} from "../lib/k8s/types";
|
|
15
|
+
|
|
16
|
+
export interface SetActivePaneAction {
|
|
17
|
+
type: "setActivePane";
|
|
18
|
+
pane: PaneId;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CyclePaneAction {
|
|
22
|
+
type: "cyclePane";
|
|
23
|
+
direction: 1 | -1;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SetOverlayAction {
|
|
27
|
+
type: "setOverlay";
|
|
28
|
+
overlay?: OverlayId | undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SetInspectorTabAction {
|
|
32
|
+
type: "setInspectorTab";
|
|
33
|
+
tab: AppState["inspectorTab"];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface SetKubectlAvailableAction {
|
|
37
|
+
type: "setKubectlAvailable";
|
|
38
|
+
available: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SetStatusMessageAction {
|
|
42
|
+
type: "setStatusMessage";
|
|
43
|
+
message: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface SetErrorAction {
|
|
47
|
+
type: "setError";
|
|
48
|
+
error?: AppError | undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SetContextsStatusAction {
|
|
52
|
+
type: "setContextsStatus";
|
|
53
|
+
status: LoadStatus;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface SetContextsAction {
|
|
57
|
+
type: "setContexts";
|
|
58
|
+
contexts: AppState["contexts"];
|
|
59
|
+
activeContext?: string | undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface SetActiveContextAction {
|
|
63
|
+
type: "setActiveContext";
|
|
64
|
+
activeContext?: string | undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface SetNamespacesStatusAction {
|
|
68
|
+
type: "setNamespacesStatus";
|
|
69
|
+
status: LoadStatus;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface SetNamespacesAction {
|
|
73
|
+
type: "setNamespaces";
|
|
74
|
+
namespaces: AppState["namespaces"];
|
|
75
|
+
activeNamespace: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface SetActiveNamespaceAction {
|
|
79
|
+
type: "setActiveNamespace";
|
|
80
|
+
namespace: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface SetResourceKindsStatusAction {
|
|
84
|
+
type: "setResourceKindsStatus";
|
|
85
|
+
status: LoadStatus;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface SetResourceKindsAction {
|
|
89
|
+
type: "setResourceKinds";
|
|
90
|
+
resourceKinds: ResourceKind[];
|
|
91
|
+
selectedKind: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface SetSelectedKindAction {
|
|
95
|
+
type: "setSelectedKind";
|
|
96
|
+
kind: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface SetResourcesStatusAction {
|
|
100
|
+
type: "setResourcesStatus";
|
|
101
|
+
status: LoadStatus;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface SetResourcesAction {
|
|
105
|
+
type: "setResources";
|
|
106
|
+
resources: ResourceListItem[];
|
|
107
|
+
selectedResourceName?: string | undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface ToggleSelectedResourceAction {
|
|
111
|
+
type: "toggleSelectedResource";
|
|
112
|
+
name: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface ClearSelectedResourcesAction {
|
|
116
|
+
type: "clearSelectedResources";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface SetResourceFilterAction {
|
|
120
|
+
type: "setResourceFilter";
|
|
121
|
+
value: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface SetSelectedResourceNameAction {
|
|
125
|
+
type: "setSelectedResourceName";
|
|
126
|
+
name?: string | undefined;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface SetSelectedResourceDetailStatusAction {
|
|
130
|
+
type: "setSelectedResourceDetailStatus";
|
|
131
|
+
status: LoadStatus;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface SetSelectedResourceDetailAction {
|
|
135
|
+
type: "setSelectedResourceDetail";
|
|
136
|
+
detail?: ResourceDetail | undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface SetEventsStatusAction {
|
|
140
|
+
type: "setEventsStatus";
|
|
141
|
+
status: LoadStatus;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface SetEventsAction {
|
|
145
|
+
type: "setEvents";
|
|
146
|
+
events: EventItem[];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface ToggleRevealDetailLineAction {
|
|
150
|
+
type: "toggleRevealDetailLine";
|
|
151
|
+
id: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface AddActivePortForwardAction {
|
|
155
|
+
type: "addActivePortForward";
|
|
156
|
+
forward: ActivePortForward;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export interface UpdateActivePortForwardAction {
|
|
160
|
+
type: "updateActivePortForward";
|
|
161
|
+
id: string;
|
|
162
|
+
patch: Partial<ActivePortForward>;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface RemoveActivePortForwardAction {
|
|
166
|
+
type: "removeActivePortForward";
|
|
167
|
+
id: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface ClearTransientViewsAction {
|
|
171
|
+
type: "clearTransientViews";
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface SetLogsDataAction {
|
|
175
|
+
type: "setLogsData";
|
|
176
|
+
logsTarget?: string | undefined;
|
|
177
|
+
logsText: string;
|
|
178
|
+
logsStatus: LoadStatus;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface SetLogsContainerAction {
|
|
182
|
+
type: "setLogsContainer";
|
|
183
|
+
container?: string | undefined;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface SetLogsOptionsAction {
|
|
187
|
+
type: "setLogsOptions";
|
|
188
|
+
options: LogOptions;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface PushNotificationAction {
|
|
192
|
+
type: "pushNotification";
|
|
193
|
+
notification: Notification;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface DismissNotificationAction {
|
|
197
|
+
type: "dismissNotification";
|
|
198
|
+
id: string;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface SetRevealedSecretValueAction {
|
|
202
|
+
type: "setRevealedSecretValue";
|
|
203
|
+
id: string;
|
|
204
|
+
value: string;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface SetPodMetricsAction {
|
|
208
|
+
type: "setPodMetrics";
|
|
209
|
+
metrics: AppState["podMetrics"];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export interface SetNodeMetricsAction {
|
|
213
|
+
type: "setNodeMetrics";
|
|
214
|
+
metrics: AppState["nodeMetrics"];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface SetHelmRollbackRevisionAction {
|
|
218
|
+
type: "setHelmRollbackRevision";
|
|
219
|
+
value: string;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export type AppAction =
|
|
223
|
+
| SetActivePaneAction
|
|
224
|
+
| CyclePaneAction
|
|
225
|
+
| SetOverlayAction
|
|
226
|
+
| SetInspectorTabAction
|
|
227
|
+
| SetKubectlAvailableAction
|
|
228
|
+
| SetStatusMessageAction
|
|
229
|
+
| SetErrorAction
|
|
230
|
+
| SetContextsStatusAction
|
|
231
|
+
| SetContextsAction
|
|
232
|
+
| SetActiveContextAction
|
|
233
|
+
| SetNamespacesStatusAction
|
|
234
|
+
| SetNamespacesAction
|
|
235
|
+
| SetActiveNamespaceAction
|
|
236
|
+
| SetResourceKindsStatusAction
|
|
237
|
+
| SetResourceKindsAction
|
|
238
|
+
| SetSelectedKindAction
|
|
239
|
+
| SetResourcesStatusAction
|
|
240
|
+
| SetResourcesAction
|
|
241
|
+
| ToggleSelectedResourceAction
|
|
242
|
+
| ClearSelectedResourcesAction
|
|
243
|
+
| SetResourceFilterAction
|
|
244
|
+
| SetSelectedResourceNameAction
|
|
245
|
+
| SetSelectedResourceDetailStatusAction
|
|
246
|
+
| SetSelectedResourceDetailAction
|
|
247
|
+
| SetEventsStatusAction
|
|
248
|
+
| SetEventsAction
|
|
249
|
+
| ToggleRevealDetailLineAction
|
|
250
|
+
| AddActivePortForwardAction
|
|
251
|
+
| UpdateActivePortForwardAction
|
|
252
|
+
| RemoveActivePortForwardAction
|
|
253
|
+
| ClearTransientViewsAction
|
|
254
|
+
| SetLogsDataAction
|
|
255
|
+
| SetLogsContainerAction
|
|
256
|
+
| SetLogsOptionsAction
|
|
257
|
+
| PushNotificationAction
|
|
258
|
+
| DismissNotificationAction
|
|
259
|
+
| SetRevealedSecretValueAction
|
|
260
|
+
| SetPodMetricsAction
|
|
261
|
+
| SetNodeMetricsAction
|
|
262
|
+
| SetHelmRollbackRevisionAction;
|