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.
Files changed (35) hide show
  1. package/README.md +194 -40
  2. package/bin/openk8s.js +2 -0
  3. package/package.json +52 -6
  4. package/src/app/app-state.ts +461 -0
  5. package/src/app/app.tsx +708 -0
  6. package/src/app/components/inspector.tsx +449 -0
  7. package/src/app/components/kind-rows.tsx +66 -0
  8. package/src/app/components/notification-tray.tsx +59 -0
  9. package/src/app/components/overlays/delete-confirm-overlay.tsx +79 -0
  10. package/src/app/components/overlays/helm-rollback-overlay.tsx +86 -0
  11. package/src/app/components/overlays/index.ts +12 -0
  12. package/src/app/components/overlays/logs-dialog.tsx +303 -0
  13. package/src/app/components/overlays/port-forward-overlay.tsx +184 -0
  14. package/src/app/components/overlays/scale-dialog.tsx +96 -0
  15. package/src/app/components/overlays/select-overlay.tsx +68 -0
  16. package/src/app/components/overlays/shared.tsx +18 -0
  17. package/src/app/components/port-forwards-tray.tsx +57 -0
  18. package/src/app/components/resource-rows.tsx +120 -0
  19. package/src/app/hooks/use-app-keyboard.ts +723 -0
  20. package/src/app/hooks/use-app-side-effects.ts +39 -0
  21. package/src/app/hooks/use-clipboard.ts +54 -0
  22. package/src/app/hooks/use-data-fetching.ts +366 -0
  23. package/src/app/hooks/use-log-stream.ts +113 -0
  24. package/src/app/hooks/use-port-forward.ts +149 -0
  25. package/src/app/persistence.ts +44 -0
  26. package/src/app/theme.ts +95 -0
  27. package/src/app/use-polling-tick.ts +27 -0
  28. package/src/app/utils.ts +274 -0
  29. package/src/index.tsx +8 -0
  30. package/src/lib/k8s/k8s-format.ts +42 -0
  31. package/src/lib/k8s/resource-detail-builder.ts +545 -0
  32. package/src/lib/k8s/resource-parser.ts +308 -0
  33. package/src/lib/k8s/types.ts +164 -0
  34. package/src/lib/kubectl/kubectl-service.ts +1116 -0
  35. 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
+ }