openk8s 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -40
- package/bin/openk8s.js +2 -0
- package/package.json +52 -6
- package/src/app/app-state.ts +461 -0
- package/src/app/app.tsx +708 -0
- package/src/app/components/inspector.tsx +449 -0
- package/src/app/components/kind-rows.tsx +66 -0
- package/src/app/components/notification-tray.tsx +59 -0
- package/src/app/components/overlays/delete-confirm-overlay.tsx +79 -0
- package/src/app/components/overlays/helm-rollback-overlay.tsx +86 -0
- package/src/app/components/overlays/index.ts +12 -0
- package/src/app/components/overlays/logs-dialog.tsx +303 -0
- package/src/app/components/overlays/port-forward-overlay.tsx +184 -0
- package/src/app/components/overlays/scale-dialog.tsx +96 -0
- package/src/app/components/overlays/select-overlay.tsx +68 -0
- package/src/app/components/overlays/shared.tsx +18 -0
- package/src/app/components/port-forwards-tray.tsx +57 -0
- package/src/app/components/resource-rows.tsx +120 -0
- package/src/app/hooks/use-app-keyboard.ts +723 -0
- package/src/app/hooks/use-app-side-effects.ts +39 -0
- package/src/app/hooks/use-clipboard.ts +54 -0
- package/src/app/hooks/use-data-fetching.ts +366 -0
- package/src/app/hooks/use-log-stream.ts +113 -0
- package/src/app/hooks/use-port-forward.ts +149 -0
- package/src/app/persistence.ts +44 -0
- package/src/app/theme.ts +95 -0
- package/src/app/use-polling-tick.ts +27 -0
- package/src/app/utils.ts +274 -0
- package/src/index.tsx +8 -0
- package/src/lib/k8s/k8s-format.ts +42 -0
- package/src/lib/k8s/resource-detail-builder.ts +545 -0
- package/src/lib/k8s/resource-parser.ts +308 -0
- package/src/lib/k8s/types.ts +164 -0
- package/src/lib/kubectl/kubectl-service.ts +1116 -0
- package/src/lib/kubectl/spawn-utils.ts +81 -0
|
@@ -0,0 +1,461 @@
|
|
|
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 const DEFAULT_NAMESPACE = "default";
|
|
17
|
+
|
|
18
|
+
export const initialState: AppState = {
|
|
19
|
+
activePane: "resources",
|
|
20
|
+
overlay: undefined,
|
|
21
|
+
inspectorTab: "summary",
|
|
22
|
+
kubectlAvailable: true,
|
|
23
|
+
statusMessage: "Starting workspace",
|
|
24
|
+
error: undefined,
|
|
25
|
+
contexts: [],
|
|
26
|
+
contextsStatus: "idle",
|
|
27
|
+
activeContext: undefined,
|
|
28
|
+
namespaces: [],
|
|
29
|
+
namespacesStatus: "idle",
|
|
30
|
+
activeNamespace: DEFAULT_NAMESPACE,
|
|
31
|
+
resourceKinds: [],
|
|
32
|
+
resourceKindsStatus: "idle",
|
|
33
|
+
selectedKind: "pods",
|
|
34
|
+
resources: [],
|
|
35
|
+
resourcesStatus: "idle",
|
|
36
|
+
resourceFilter: "",
|
|
37
|
+
selectedResourceName: undefined,
|
|
38
|
+
selectedResourceNames: [],
|
|
39
|
+
selectedResourceDetail: undefined,
|
|
40
|
+
selectedResourceDetailStatus: "idle",
|
|
41
|
+
events: [],
|
|
42
|
+
eventsStatus: "idle",
|
|
43
|
+
logsTarget: undefined,
|
|
44
|
+
logsText: "",
|
|
45
|
+
logsStatus: "idle",
|
|
46
|
+
logsContainer: undefined,
|
|
47
|
+
logsOptions: { tail: 120, previous: false },
|
|
48
|
+
revealedDetailLineIds: [],
|
|
49
|
+
revealedSecretValues: {},
|
|
50
|
+
activePortForwards: [],
|
|
51
|
+
notifications: [],
|
|
52
|
+
podMetrics: {},
|
|
53
|
+
nodeMetrics: {},
|
|
54
|
+
helmRollbackRevision: "",
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export interface SetActivePaneAction {
|
|
58
|
+
type: "setActivePane";
|
|
59
|
+
pane: PaneId;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface CyclePaneAction {
|
|
63
|
+
type: "cyclePane";
|
|
64
|
+
direction: 1 | -1;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface SetOverlayAction {
|
|
68
|
+
type: "setOverlay";
|
|
69
|
+
overlay?: OverlayId | undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface SetInspectorTabAction {
|
|
73
|
+
type: "setInspectorTab";
|
|
74
|
+
tab: AppState["inspectorTab"];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface SetKubectlAvailableAction {
|
|
78
|
+
type: "setKubectlAvailable";
|
|
79
|
+
available: boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface SetStatusMessageAction {
|
|
83
|
+
type: "setStatusMessage";
|
|
84
|
+
message: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface SetErrorAction {
|
|
88
|
+
type: "setError";
|
|
89
|
+
error?: AppError | undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface SetContextsStatusAction {
|
|
93
|
+
type: "setContextsStatus";
|
|
94
|
+
status: LoadStatus;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface SetContextsAction {
|
|
98
|
+
type: "setContexts";
|
|
99
|
+
contexts: AppState["contexts"];
|
|
100
|
+
activeContext?: string | undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface SetActiveContextAction {
|
|
104
|
+
type: "setActiveContext";
|
|
105
|
+
activeContext?: string | undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface SetNamespacesStatusAction {
|
|
109
|
+
type: "setNamespacesStatus";
|
|
110
|
+
status: LoadStatus;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface SetNamespacesAction {
|
|
114
|
+
type: "setNamespaces";
|
|
115
|
+
namespaces: AppState["namespaces"];
|
|
116
|
+
activeNamespace: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface SetActiveNamespaceAction {
|
|
120
|
+
type: "setActiveNamespace";
|
|
121
|
+
namespace: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface SetResourceKindsStatusAction {
|
|
125
|
+
type: "setResourceKindsStatus";
|
|
126
|
+
status: LoadStatus;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface SetResourceKindsAction {
|
|
130
|
+
type: "setResourceKinds";
|
|
131
|
+
resourceKinds: ResourceKind[];
|
|
132
|
+
selectedKind: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface SetSelectedKindAction {
|
|
136
|
+
type: "setSelectedKind";
|
|
137
|
+
kind: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface SetResourcesStatusAction {
|
|
141
|
+
type: "setResourcesStatus";
|
|
142
|
+
status: LoadStatus;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface SetResourcesAction {
|
|
146
|
+
type: "setResources";
|
|
147
|
+
resources: ResourceListItem[];
|
|
148
|
+
selectedResourceName?: string | undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface ToggleSelectedResourceAction {
|
|
152
|
+
type: "toggleSelectedResource";
|
|
153
|
+
name: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface ClearSelectedResourcesAction {
|
|
157
|
+
type: "clearSelectedResources";
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface SetResourceFilterAction {
|
|
161
|
+
type: "setResourceFilter";
|
|
162
|
+
value: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface SetSelectedResourceNameAction {
|
|
166
|
+
type: "setSelectedResourceName";
|
|
167
|
+
name?: string | undefined;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface SetSelectedResourceDetailStatusAction {
|
|
171
|
+
type: "setSelectedResourceDetailStatus";
|
|
172
|
+
status: LoadStatus;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface SetSelectedResourceDetailAction {
|
|
176
|
+
type: "setSelectedResourceDetail";
|
|
177
|
+
detail?: ResourceDetail | undefined;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface SetEventsStatusAction {
|
|
181
|
+
type: "setEventsStatus";
|
|
182
|
+
status: LoadStatus;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface SetEventsAction {
|
|
186
|
+
type: "setEvents";
|
|
187
|
+
events: EventItem[];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface ToggleRevealDetailLineAction {
|
|
191
|
+
type: "toggleRevealDetailLine";
|
|
192
|
+
id: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface AddActivePortForwardAction {
|
|
196
|
+
type: "addActivePortForward";
|
|
197
|
+
forward: ActivePortForward;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export interface UpdateActivePortForwardAction {
|
|
201
|
+
type: "updateActivePortForward";
|
|
202
|
+
id: string;
|
|
203
|
+
patch: Partial<ActivePortForward>;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export interface RemoveActivePortForwardAction {
|
|
207
|
+
type: "removeActivePortForward";
|
|
208
|
+
id: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export interface ClearTransientViewsAction {
|
|
212
|
+
type: "clearTransientViews";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export interface SetLogsDataAction {
|
|
216
|
+
type: "setLogsData";
|
|
217
|
+
logsTarget?: string | undefined;
|
|
218
|
+
logsText: string;
|
|
219
|
+
logsStatus: LoadStatus;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface SetLogsContainerAction {
|
|
223
|
+
type: "setLogsContainer";
|
|
224
|
+
container?: string | undefined;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface SetLogsOptionsAction {
|
|
228
|
+
type: "setLogsOptions";
|
|
229
|
+
options: LogOptions;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export interface PushNotificationAction {
|
|
233
|
+
type: "pushNotification";
|
|
234
|
+
notification: Notification;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface DismissNotificationAction {
|
|
238
|
+
type: "dismissNotification";
|
|
239
|
+
id: string;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export interface SetRevealedSecretValueAction {
|
|
243
|
+
type: "setRevealedSecretValue";
|
|
244
|
+
id: string;
|
|
245
|
+
value: string;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export interface SetPodMetricsAction {
|
|
249
|
+
type: "setPodMetrics";
|
|
250
|
+
metrics: AppState["podMetrics"];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export interface SetNodeMetricsAction {
|
|
254
|
+
type: "setNodeMetrics";
|
|
255
|
+
metrics: AppState["nodeMetrics"];
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export interface SetHelmRollbackRevisionAction {
|
|
259
|
+
type: "setHelmRollbackRevision";
|
|
260
|
+
value: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export type AppAction =
|
|
264
|
+
| SetActivePaneAction
|
|
265
|
+
| CyclePaneAction
|
|
266
|
+
| SetOverlayAction
|
|
267
|
+
| SetInspectorTabAction
|
|
268
|
+
| SetKubectlAvailableAction
|
|
269
|
+
| SetStatusMessageAction
|
|
270
|
+
| SetErrorAction
|
|
271
|
+
| SetContextsStatusAction
|
|
272
|
+
| SetContextsAction
|
|
273
|
+
| SetActiveContextAction
|
|
274
|
+
| SetNamespacesStatusAction
|
|
275
|
+
| SetNamespacesAction
|
|
276
|
+
| SetActiveNamespaceAction
|
|
277
|
+
| SetResourceKindsStatusAction
|
|
278
|
+
| SetResourceKindsAction
|
|
279
|
+
| SetSelectedKindAction
|
|
280
|
+
| SetResourcesStatusAction
|
|
281
|
+
| SetResourcesAction
|
|
282
|
+
| ToggleSelectedResourceAction
|
|
283
|
+
| ClearSelectedResourcesAction
|
|
284
|
+
| SetResourceFilterAction
|
|
285
|
+
| SetSelectedResourceNameAction
|
|
286
|
+
| SetSelectedResourceDetailStatusAction
|
|
287
|
+
| SetSelectedResourceDetailAction
|
|
288
|
+
| SetEventsStatusAction
|
|
289
|
+
| SetEventsAction
|
|
290
|
+
| ToggleRevealDetailLineAction
|
|
291
|
+
| AddActivePortForwardAction
|
|
292
|
+
| UpdateActivePortForwardAction
|
|
293
|
+
| RemoveActivePortForwardAction
|
|
294
|
+
| ClearTransientViewsAction
|
|
295
|
+
| SetLogsDataAction
|
|
296
|
+
| SetLogsContainerAction
|
|
297
|
+
| SetLogsOptionsAction
|
|
298
|
+
| PushNotificationAction
|
|
299
|
+
| DismissNotificationAction
|
|
300
|
+
| SetRevealedSecretValueAction
|
|
301
|
+
| SetPodMetricsAction
|
|
302
|
+
| SetNodeMetricsAction
|
|
303
|
+
| SetHelmRollbackRevisionAction;
|
|
304
|
+
|
|
305
|
+
const PANE_ORDER: PaneId[] = ["clusters", "resources", "inspector"];
|
|
306
|
+
|
|
307
|
+
export function reducer(state: AppState, action: AppAction): AppState {
|
|
308
|
+
switch (action.type) {
|
|
309
|
+
case "setActivePane":
|
|
310
|
+
return { ...state, activePane: action.pane };
|
|
311
|
+
case "cyclePane": {
|
|
312
|
+
const currentIndex = PANE_ORDER.indexOf(state.activePane);
|
|
313
|
+
const nextIndex = (currentIndex + action.direction + PANE_ORDER.length) % PANE_ORDER.length;
|
|
314
|
+
return { ...state, activePane: PANE_ORDER[nextIndex] ?? state.activePane };
|
|
315
|
+
}
|
|
316
|
+
case "setOverlay":
|
|
317
|
+
return { ...state, overlay: action.overlay };
|
|
318
|
+
case "setInspectorTab":
|
|
319
|
+
return { ...state, inspectorTab: action.tab };
|
|
320
|
+
case "setKubectlAvailable":
|
|
321
|
+
return { ...state, kubectlAvailable: action.available };
|
|
322
|
+
case "setStatusMessage":
|
|
323
|
+
return { ...state, statusMessage: action.message };
|
|
324
|
+
case "setError":
|
|
325
|
+
return { ...state, error: action.error };
|
|
326
|
+
case "setContextsStatus":
|
|
327
|
+
return { ...state, contextsStatus: action.status };
|
|
328
|
+
case "setContexts":
|
|
329
|
+
return {
|
|
330
|
+
...state,
|
|
331
|
+
contexts: action.contexts,
|
|
332
|
+
activeContext: action.activeContext,
|
|
333
|
+
};
|
|
334
|
+
case "setActiveContext":
|
|
335
|
+
return { ...state, activeContext: action.activeContext };
|
|
336
|
+
case "setNamespacesStatus":
|
|
337
|
+
return { ...state, namespacesStatus: action.status };
|
|
338
|
+
case "setNamespaces":
|
|
339
|
+
return {
|
|
340
|
+
...state,
|
|
341
|
+
namespaces: action.namespaces,
|
|
342
|
+
activeNamespace: action.activeNamespace,
|
|
343
|
+
};
|
|
344
|
+
case "setActiveNamespace":
|
|
345
|
+
return { ...state, activeNamespace: action.namespace };
|
|
346
|
+
case "setResourceKindsStatus":
|
|
347
|
+
return { ...state, resourceKindsStatus: action.status };
|
|
348
|
+
case "setResourceKinds":
|
|
349
|
+
return {
|
|
350
|
+
...state,
|
|
351
|
+
resourceKinds: action.resourceKinds,
|
|
352
|
+
selectedKind: action.selectedKind,
|
|
353
|
+
};
|
|
354
|
+
case "setSelectedKind":
|
|
355
|
+
return { ...state, selectedKind: action.kind, resourceFilter: "", selectedResourceNames: [] };
|
|
356
|
+
case "setResourcesStatus":
|
|
357
|
+
return { ...state, resourcesStatus: action.status };
|
|
358
|
+
case "setResources":
|
|
359
|
+
return {
|
|
360
|
+
...state,
|
|
361
|
+
resources: action.resources,
|
|
362
|
+
selectedResourceName: action.selectedResourceName,
|
|
363
|
+
selectedResourceNames: state.selectedResourceNames.filter((name) => action.resources.some((resource) => resource.ref.name === name)),
|
|
364
|
+
};
|
|
365
|
+
case "toggleSelectedResource":
|
|
366
|
+
return {
|
|
367
|
+
...state,
|
|
368
|
+
selectedResourceNames: state.selectedResourceNames.includes(action.name)
|
|
369
|
+
? state.selectedResourceNames.filter((name) => name !== action.name)
|
|
370
|
+
: [...state.selectedResourceNames, action.name],
|
|
371
|
+
};
|
|
372
|
+
case "clearSelectedResources":
|
|
373
|
+
return { ...state, selectedResourceNames: [] };
|
|
374
|
+
case "setResourceFilter":
|
|
375
|
+
return { ...state, resourceFilter: action.value };
|
|
376
|
+
case "setSelectedResourceName":
|
|
377
|
+
return { ...state, selectedResourceName: action.name };
|
|
378
|
+
case "setSelectedResourceDetailStatus":
|
|
379
|
+
return { ...state, selectedResourceDetailStatus: action.status };
|
|
380
|
+
case "setSelectedResourceDetail":
|
|
381
|
+
return { ...state, selectedResourceDetail: action.detail };
|
|
382
|
+
case "setEventsStatus":
|
|
383
|
+
return { ...state, eventsStatus: action.status };
|
|
384
|
+
case "setEvents":
|
|
385
|
+
return { ...state, events: action.events };
|
|
386
|
+
case "toggleRevealDetailLine":
|
|
387
|
+
return {
|
|
388
|
+
...state,
|
|
389
|
+
revealedDetailLineIds: state.revealedDetailLineIds.includes(action.id)
|
|
390
|
+
? state.revealedDetailLineIds.filter((id) => id !== action.id)
|
|
391
|
+
: [...state.revealedDetailLineIds, action.id],
|
|
392
|
+
};
|
|
393
|
+
case "addActivePortForward":
|
|
394
|
+
return {
|
|
395
|
+
...state,
|
|
396
|
+
activePortForwards: [...state.activePortForwards, action.forward],
|
|
397
|
+
};
|
|
398
|
+
case "updateActivePortForward":
|
|
399
|
+
return {
|
|
400
|
+
...state,
|
|
401
|
+
activePortForwards: state.activePortForwards.map((forward) =>
|
|
402
|
+
forward.id === action.id ? { ...forward, ...action.patch } : forward,
|
|
403
|
+
),
|
|
404
|
+
};
|
|
405
|
+
case "removeActivePortForward":
|
|
406
|
+
return {
|
|
407
|
+
...state,
|
|
408
|
+
activePortForwards: state.activePortForwards.filter((forward) => forward.id !== action.id),
|
|
409
|
+
};
|
|
410
|
+
case "clearTransientViews":
|
|
411
|
+
return {
|
|
412
|
+
...state,
|
|
413
|
+
events: [],
|
|
414
|
+
eventsStatus: "idle",
|
|
415
|
+
logsTarget: undefined,
|
|
416
|
+
logsText: "",
|
|
417
|
+
logsStatus: "idle",
|
|
418
|
+
logsContainer: undefined,
|
|
419
|
+
revealedDetailLineIds: [],
|
|
420
|
+
revealedSecretValues: {},
|
|
421
|
+
selectedResourceNames: [],
|
|
422
|
+
};
|
|
423
|
+
case "setLogsData":
|
|
424
|
+
return {
|
|
425
|
+
...state,
|
|
426
|
+
logsTarget: action.logsTarget,
|
|
427
|
+
logsText: action.logsText,
|
|
428
|
+
logsStatus: action.logsStatus,
|
|
429
|
+
};
|
|
430
|
+
case "setLogsContainer":
|
|
431
|
+
return { ...state, logsContainer: action.container };
|
|
432
|
+
case "setLogsOptions":
|
|
433
|
+
return { ...state, logsOptions: action.options };
|
|
434
|
+
case "pushNotification":
|
|
435
|
+
return {
|
|
436
|
+
...state,
|
|
437
|
+
notifications: [...state.notifications, action.notification],
|
|
438
|
+
};
|
|
439
|
+
case "dismissNotification":
|
|
440
|
+
return {
|
|
441
|
+
...state,
|
|
442
|
+
notifications: state.notifications.filter((n) => n.id !== action.id),
|
|
443
|
+
};
|
|
444
|
+
case "setRevealedSecretValue":
|
|
445
|
+
return {
|
|
446
|
+
...state,
|
|
447
|
+
revealedSecretValues: {
|
|
448
|
+
...state.revealedSecretValues,
|
|
449
|
+
[action.id]: action.value,
|
|
450
|
+
},
|
|
451
|
+
};
|
|
452
|
+
case "setPodMetrics":
|
|
453
|
+
return { ...state, podMetrics: action.metrics };
|
|
454
|
+
case "setNodeMetrics":
|
|
455
|
+
return { ...state, nodeMetrics: action.metrics };
|
|
456
|
+
case "setHelmRollbackRevision":
|
|
457
|
+
return { ...state, helmRollbackRevision: action.value };
|
|
458
|
+
default:
|
|
459
|
+
return state;
|
|
460
|
+
}
|
|
461
|
+
}
|