mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Catch metadata being undefined at KubeObject creation (#3960)
This commit is contained in:
parent
433c2c0d4d
commit
913244b204
@ -98,6 +98,12 @@ export interface KubeObjectStatus {
|
||||
|
||||
export type KubeMetaField = keyof KubeObjectMetadata;
|
||||
|
||||
export class KubeCreationError extends Error {
|
||||
constructor(message: string, public data: any) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata, Status = any, Spec = any> implements ItemObject {
|
||||
static readonly kind: string;
|
||||
static readonly namespaced: boolean;
|
||||
@ -209,10 +215,14 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
|
||||
]);
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
if (typeof data !== "object") {
|
||||
if (typeof data !== "object") {
|
||||
throw new TypeError(`Cannot create a KubeObject from ${typeof data}`);
|
||||
}
|
||||
|
||||
if (!data.metadata || typeof data.metadata !== "object") {
|
||||
throw new KubeCreationError(`Cannot create a KubeObject from an object without metadata`, data);
|
||||
}
|
||||
|
||||
Object.assign(this, data);
|
||||
autoBind(this);
|
||||
}
|
||||
@ -274,7 +284,7 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
|
||||
}
|
||||
|
||||
getOwnerRefs() {
|
||||
const refs = this.metadata?.ownerReferences || [];
|
||||
const refs = this.metadata.ownerReferences || [];
|
||||
const namespace = this.getNs();
|
||||
|
||||
return refs.map(ownerRef => ({ ...ownerRef, namespace }));
|
||||
|
||||
@ -25,9 +25,11 @@ import { Pod } from "../../../../common/k8s-api/endpoints";
|
||||
import { ThemeStore } from "../../../theme.store";
|
||||
import { dockStore } from "../dock.store";
|
||||
import { logTabStore } from "../log-tab.store";
|
||||
import { TerminalStore } from "../terminal.store";
|
||||
import { deploymentPod1, deploymentPod2, deploymentPod3, dockerPod } from "./pod.mock";
|
||||
import fse from "fs-extra";
|
||||
import { mockWindow } from "../../../../../__mocks__/windowMock";
|
||||
|
||||
mockWindow();
|
||||
|
||||
jest.mock("react-monaco-editor", () => null);
|
||||
|
||||
@ -45,7 +47,6 @@ describe("log tab store", () => {
|
||||
beforeEach(() => {
|
||||
UserStore.createInstance();
|
||||
ThemeStore.createInstance();
|
||||
TerminalStore.createInstance();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -53,7 +54,6 @@ describe("log tab store", () => {
|
||||
dockStore.reset();
|
||||
UserStore.resetInstance();
|
||||
ThemeStore.resetInstance();
|
||||
TerminalStore.resetInstance();
|
||||
fse.remove("tmp");
|
||||
});
|
||||
|
||||
@ -135,11 +135,11 @@ describe("log tab store", () => {
|
||||
});
|
||||
|
||||
// FIXME: this is failed when it's not .only == depends on something above
|
||||
it.only("closes tab if no pods left in store", () => {
|
||||
it.only("closes tab if no pods left in store", async () => {
|
||||
const selectedPod = new Pod(deploymentPod1);
|
||||
const selectedContainer = selectedPod.getInitContainers()[0];
|
||||
|
||||
logTabStore.createPodTab({
|
||||
const id = logTabStore.createPodTab({
|
||||
selectedPod,
|
||||
selectedContainer
|
||||
});
|
||||
@ -147,6 +147,7 @@ describe("log tab store", () => {
|
||||
podsStore.items.clear();
|
||||
|
||||
expect(logTabStore.getData(dockStore.selectedTabId)).toBeUndefined();
|
||||
expect(dockStore.getTabById(dockStore.selectedTabId)).toBeUndefined();
|
||||
expect(logTabStore.getData(id)).toBeUndefined();
|
||||
expect(dockStore.getTabById(id)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -160,7 +160,7 @@ export class DockStore implements DockStorageState {
|
||||
window.addEventListener("resize", throttle(this.adjustHeight, 250));
|
||||
// create monaco models
|
||||
this.whenReady.then(() => {this.tabs.forEach(tab => {
|
||||
if (this.usesMonacoEditor(tab)) {
|
||||
if (this.usesMonacoEditor(tab)) {
|
||||
monacoModelsManager.addModel(tab.id);
|
||||
}
|
||||
});});
|
||||
@ -274,7 +274,7 @@ export class DockStore implements DockStorageState {
|
||||
title
|
||||
};
|
||||
|
||||
// add monaco model
|
||||
// add monaco model
|
||||
if (this.usesMonacoEditor(tab)) {
|
||||
monacoModelsManager.addModel(id);
|
||||
}
|
||||
@ -287,14 +287,14 @@ export class DockStore implements DockStorageState {
|
||||
}
|
||||
|
||||
@action
|
||||
async closeTab(tabId: TabId) {
|
||||
closeTab(tabId: TabId) {
|
||||
const tab = this.getTabById(tabId);
|
||||
|
||||
if (!tab || tab.pinned) {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove monaco model
|
||||
// remove monaco model
|
||||
if (this.usesMonacoEditor(tab)) {
|
||||
monacoModelsManager.removeModel(tabId);
|
||||
}
|
||||
@ -305,12 +305,6 @@ export class DockStore implements DockStorageState {
|
||||
if (this.tabs.length) {
|
||||
const newTab = this.tabs.slice(-1)[0]; // last
|
||||
|
||||
if (newTab?.kind === TabKind.TERMINAL) {
|
||||
// close the dock when selected sibling inactive terminal tab
|
||||
const { TerminalStore } = await import("./terminal.store");
|
||||
|
||||
if (!TerminalStore.getInstance(false)?.isConnected(newTab.id)) this.close();
|
||||
}
|
||||
this.selectTab(newTab.id);
|
||||
} else {
|
||||
this.selectedTabId = null;
|
||||
|
||||
@ -25,6 +25,7 @@ import { podsStore } from "../+workloads-pods/pods.store";
|
||||
|
||||
import { IPodContainer, Pod } from "../../../common/k8s-api/endpoints";
|
||||
import type { WorkloadKubeObject } from "../../../common/k8s-api/workload-kube-object";
|
||||
import logger from "../../../common/logger";
|
||||
import { DockTabStore } from "./dock-tab.store";
|
||||
import { dockStore, DockTabCreateSpecific, TabKind } from "./dock.store";
|
||||
|
||||
@ -51,17 +52,15 @@ export class LogTabStore extends DockTabStore<LogTabData> {
|
||||
storageKey: "pod_logs"
|
||||
});
|
||||
|
||||
reaction(() => podsStore.items.length, () => {
|
||||
this.updateTabsData();
|
||||
});
|
||||
reaction(() => podsStore.items.length, () => this.updateTabsData());
|
||||
}
|
||||
|
||||
createPodTab({ selectedPod, selectedContainer }: PodLogsTabData): void {
|
||||
createPodTab({ selectedPod, selectedContainer }: PodLogsTabData): string {
|
||||
const podOwner = selectedPod.getOwnerRefs()[0];
|
||||
const pods = podsStore.getPodsByOwnerId(podOwner?.uid);
|
||||
const title = `Pod ${selectedPod.getName()}`;
|
||||
|
||||
this.createLogsTab(title, {
|
||||
return this.createLogsTab(title, {
|
||||
pods: pods.length ? pods : [selectedPod],
|
||||
selectedPod,
|
||||
selectedContainer
|
||||
@ -95,9 +94,9 @@ export class LogTabStore extends DockTabStore<LogTabData> {
|
||||
...tabParams,
|
||||
kind: TabKind.POD_LOGS,
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
private createLogsTab(title: string, data: LogTabData) {
|
||||
private createLogsTab(title: string, data: LogTabData): string {
|
||||
const id = uniqueId("log-tab-");
|
||||
|
||||
this.createDockTab({ id, title });
|
||||
@ -106,38 +105,45 @@ export class LogTabStore extends DockTabStore<LogTabData> {
|
||||
showTimestamps: false,
|
||||
previous: false
|
||||
});
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private async updateTabsData() {
|
||||
const promises: Promise<void>[] = [];
|
||||
|
||||
private updateTabsData() {
|
||||
for (const [tabId, tabData] of this.data) {
|
||||
const pod = new Pod(tabData.selectedPod);
|
||||
const pods = podsStore.getPodsByOwnerId(pod.getOwnerRefs()[0]?.uid);
|
||||
const isSelectedPodInList = pods.find(item => item.getId() == pod.getId());
|
||||
const selectedPod = isSelectedPodInList ? pod : pods[0];
|
||||
const selectedContainer = isSelectedPodInList ? tabData.selectedContainer : pod.getAllContainers()[0];
|
||||
try {
|
||||
if (!tabData.selectedPod) {
|
||||
tabData.selectedPod = tabData.pods[0];
|
||||
}
|
||||
|
||||
if (pods.length) {
|
||||
this.setData(tabId, {
|
||||
...tabData,
|
||||
selectedPod,
|
||||
selectedContainer,
|
||||
pods
|
||||
});
|
||||
|
||||
this.renameTab(tabId);
|
||||
} else {
|
||||
promises.push(this.closeTab(tabId));
|
||||
const pod = new Pod(tabData.selectedPod);
|
||||
const pods = podsStore.getPodsByOwnerId(pod.getOwnerRefs()[0]?.uid);
|
||||
const isSelectedPodInList = pods.find(item => item.getId() == pod.getId());
|
||||
const selectedPod = isSelectedPodInList ? pod : pods[0];
|
||||
const selectedContainer = isSelectedPodInList ? tabData.selectedContainer : pod.getAllContainers()[0];
|
||||
|
||||
if (pods.length > 0) {
|
||||
this.setData(tabId, {
|
||||
...tabData,
|
||||
selectedPod,
|
||||
selectedContainer,
|
||||
pods
|
||||
});
|
||||
|
||||
this.renameTab(tabId);
|
||||
} else {
|
||||
this.closeTab(tabId);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`[LOG-TAB-STORE]: failed to set data for tabId=${tabId} deleting`, error,);
|
||||
this.data.delete(tabId);
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
private async closeTab(tabId: string) {
|
||||
private closeTab(tabId: string) {
|
||||
this.clearData(tabId);
|
||||
await dockStore.closeTab(tabId);
|
||||
dockStore.closeTab(tabId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user