mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Cherry-pick from 4.2.3 (#2628)
* Fix: logs data disapearing causing crashes (#2566) Signed-off-by: Sebastian Malton <sebastian@malton.name> * Refactor helm-chart.api and improve kube validation and error handling (#2265) Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix: HPA's not sortable by age (#2565) Signed-off-by: Sebastian Malton <sebastian@malton.name> * Conditionally render status icon for kube meta (#2298) Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix custom resource loading spinner appears above extensions' cluster menus (#2344) Signed-off-by: Sebastian Malton <sebastian@malton.name> * Lens should point to the release docs (#2268) Signed-off-by: Sebastian Malton <sebastian@malton.name> * Refactor the Extensions settings page (#2221) Signed-off-by: Sebastian Malton <sebastian@malton.name> * try and get jest to not core dump Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
7fde8125eb
commit
1f854d0a0f
42 files changed
+1777
-1067
No files matched your search
@@ -1,10 +1,14 @@
|
||||
import mockFs from "mock-fs";
|
||||
import { watch } from "chokidar";
|
||||
import { join, normalize } from "path";
|
||||
import { ExtensionDiscovery, InstalledExtension } from "../extension-discovery";
|
||||
import { ExtensionsStore } from "../extensions-store";
|
||||
import path from "path";
|
||||
import { ExtensionDiscovery } from "../extension-discovery";
|
||||
import os from "os";
|
||||
import { Console } from "console";
|
||||
|
||||
jest.setTimeout(60_000);
|
||||
|
||||
jest.mock("../../common/ipc");
|
||||
jest.mock("fs-extra");
|
||||
jest.mock("chokidar", () => ({
|
||||
watch: jest.fn()
|
||||
}));
|
||||
@@ -15,6 +19,7 @@ jest.mock("../extension-installer", () => ({
|
||||
}
|
||||
}));
|
||||
|
||||
console = new Console(process.stdout, process.stderr); // fix mockFS
|
||||
const mockedWatch = watch as jest.MockedFunction<typeof watch>;
|
||||
|
||||
describe("ExtensionDiscovery", () => {
|
||||
@@ -24,47 +29,59 @@ describe("ExtensionDiscovery", () => {
|
||||
ExtensionsStore.createInstance();
|
||||
});
|
||||
|
||||
it("emits add for added extension", async done => {
|
||||
globalThis.__non_webpack_require__.mockImplementation(() => ({
|
||||
name: "my-extension"
|
||||
}));
|
||||
let addHandler: (filePath: string) => void;
|
||||
|
||||
const mockWatchInstance: any = {
|
||||
on: jest.fn((event: string, handler: typeof addHandler) => {
|
||||
if (event === "add") {
|
||||
addHandler = handler;
|
||||
}
|
||||
|
||||
return mockWatchInstance;
|
||||
})
|
||||
};
|
||||
|
||||
mockedWatch.mockImplementationOnce(() =>
|
||||
(mockWatchInstance) as any
|
||||
);
|
||||
const extensionDiscovery = ExtensionDiscovery.createInstance();
|
||||
|
||||
// Need to force isLoaded to be true so that the file watching is started
|
||||
extensionDiscovery.isLoaded = true;
|
||||
|
||||
await extensionDiscovery.watchExtensions();
|
||||
|
||||
extensionDiscovery.events.on("add", (extension: InstalledExtension) => {
|
||||
expect(extension).toEqual({
|
||||
absolutePath: expect.any(String),
|
||||
id: normalize("node_modules/my-extension/package.json"),
|
||||
isBundled: false,
|
||||
isEnabled: false,
|
||||
manifest: {
|
||||
name: "my-extension",
|
||||
},
|
||||
manifestPath: normalize("node_modules/my-extension/package.json"),
|
||||
describe("with mockFs", () => {
|
||||
beforeEach(() => {
|
||||
mockFs({
|
||||
[`${os.homedir()}/.k8slens/extensions/my-extension/package.json`]: JSON.stringify({
|
||||
name: "my-extension"
|
||||
}),
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
addHandler(join(extensionDiscovery.localFolderPath, "/my-extension/package.json"));
|
||||
afterEach(() => {
|
||||
mockFs.restore();
|
||||
});
|
||||
|
||||
it("emits add for added extension", async (done) => {
|
||||
let addHandler: (filePath: string) => void;
|
||||
|
||||
const mockWatchInstance: any = {
|
||||
on: jest.fn((event: string, handler: typeof addHandler) => {
|
||||
if (event === "add") {
|
||||
addHandler = handler;
|
||||
}
|
||||
|
||||
return mockWatchInstance;
|
||||
})
|
||||
};
|
||||
|
||||
mockedWatch.mockImplementationOnce(() =>
|
||||
(mockWatchInstance) as any
|
||||
);
|
||||
|
||||
const extensionDiscovery = ExtensionDiscovery.createInstance();
|
||||
|
||||
// Need to force isLoaded to be true so that the file watching is started
|
||||
extensionDiscovery.isLoaded = true;
|
||||
|
||||
await extensionDiscovery.watchExtensions();
|
||||
|
||||
extensionDiscovery.events.on("add", extension => {
|
||||
expect(extension).toEqual({
|
||||
absolutePath: expect.any(String),
|
||||
id: path.normalize("node_modules/my-extension/package.json"),
|
||||
isBundled: false,
|
||||
isEnabled: false,
|
||||
manifest: {
|
||||
name: "my-extension",
|
||||
},
|
||||
manifestPath: path.normalize("node_modules/my-extension/package.json"),
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
addHandler(path.join(extensionDiscovery.localFolderPath, "/my-extension/package.json"));
|
||||
});
|
||||
});
|
||||
|
||||
it("doesn't emit add for added file under extension", async done => {
|
||||
@@ -94,7 +111,7 @@ describe("ExtensionDiscovery", () => {
|
||||
|
||||
extensionDiscovery.events.on("add", onAdd);
|
||||
|
||||
addHandler(join(extensionDiscovery.localFolderPath, "/my-extension/node_modules/dep/package.json"));
|
||||
addHandler(path.join(extensionDiscovery.localFolderPath, "/my-extension/node_modules/dep/package.json"));
|
||||
|
||||
setTimeout(() => {
|
||||
expect(onAdd).not.toHaveBeenCalled();
|
||||
|
||||
@@ -1,31 +1,33 @@
|
||||
import { watch } from "chokidar";
|
||||
import { ipcRenderer } from "electron";
|
||||
import { EventEmitter } from "events";
|
||||
import fs from "fs-extra";
|
||||
import fse from "fs-extra";
|
||||
import { observable, reaction, toJS, when } from "mobx";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { broadcastMessage, handleRequest, requestMain, subscribeToBroadcast } from "../common/ipc";
|
||||
import { Singleton } from "../common/utils";
|
||||
import logger from "../main/logger";
|
||||
import { ExtensionInstallationStateStore } from "../renderer/components/+extensions/extension-install.store";
|
||||
import { extensionInstaller, PackageJson } from "./extension-installer";
|
||||
import { ExtensionsStore } from "./extensions-store";
|
||||
import { ExtensionLoader } from "./extension-loader";
|
||||
import type { LensExtensionId, LensExtensionManifest } from "./lens-extension";
|
||||
|
||||
export interface InstalledExtension {
|
||||
id: LensExtensionId;
|
||||
id: LensExtensionId;
|
||||
|
||||
readonly manifest: LensExtensionManifest;
|
||||
readonly manifest: LensExtensionManifest;
|
||||
|
||||
// Absolute path to the non-symlinked source folder,
|
||||
// e.g. "/Users/user/.k8slens/extensions/helloworld"
|
||||
readonly absolutePath: string;
|
||||
// Absolute path to the non-symlinked source folder,
|
||||
// e.g. "/Users/user/.k8slens/extensions/helloworld"
|
||||
readonly absolutePath: string;
|
||||
|
||||
// Absolute to the symlinked package.json file
|
||||
readonly manifestPath: string;
|
||||
readonly isBundled: boolean; // defined in project root's package.json
|
||||
isEnabled: boolean;
|
||||
}
|
||||
// Absolute to the symlinked package.json file
|
||||
readonly manifestPath: string;
|
||||
readonly isBundled: boolean; // defined in project root's package.json
|
||||
isEnabled: boolean;
|
||||
}
|
||||
|
||||
const logModule = "[EXTENSION-DISCOVERY]";
|
||||
|
||||
@@ -39,7 +41,7 @@ interface ExtensionDiscoveryChannelMessage {
|
||||
* Returns true if the lstat is for a directory-like file (e.g. isDirectory or symbolic link)
|
||||
* @param lstat the stats to compare
|
||||
*/
|
||||
const isDirectoryLike = (lstat: fs.Stats) => lstat.isDirectory() || lstat.isSymbolicLink();
|
||||
const isDirectoryLike = (lstat: fse.Stats) => lstat.isDirectory() || lstat.isSymbolicLink();
|
||||
|
||||
/**
|
||||
* Discovers installed bundled and local extensions from the filesystem.
|
||||
@@ -64,12 +66,7 @@ export class ExtensionDiscovery extends Singleton {
|
||||
// IPC channel to broadcast changes to extension-discovery from main
|
||||
protected static readonly extensionDiscoveryChannel = "extension-discovery:main";
|
||||
|
||||
public events: EventEmitter;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.events = new EventEmitter();
|
||||
}
|
||||
public events = new EventEmitter();
|
||||
|
||||
get localFolderPath(): string {
|
||||
return path.join(os.homedir(), ".k8slens", "extensions");
|
||||
@@ -146,8 +143,10 @@ export class ExtensionDiscovery extends Singleton {
|
||||
})
|
||||
// Extension add is detected by watching "<extensionDir>/package.json" add
|
||||
.on("add", this.handleWatchFileAdd)
|
||||
// Extension remove is detected by watching <extensionDir>" unlink
|
||||
.on("unlinkDir", this.handleWatchUnlinkDir);
|
||||
// Extension remove is detected by watching "<extensionDir>" unlink
|
||||
.on("unlinkDir", this.handleWatchUnlinkEvent)
|
||||
// Extension remove is detected by watching "<extensionSymLink>" unlink
|
||||
.on("unlink", this.handleWatchUnlinkEvent);
|
||||
}
|
||||
|
||||
handleWatchFileAdd = async (manifestPath: string) => {
|
||||
@@ -161,6 +160,7 @@ export class ExtensionDiscovery extends Singleton {
|
||||
|
||||
if (path.basename(manifestPath) === manifestFilename && isUnderLocalFolderPath) {
|
||||
try {
|
||||
ExtensionInstallationStateStore.setInstallingFromMain(manifestPath);
|
||||
const absPath = path.dirname(manifestPath);
|
||||
|
||||
// this.loadExtensionFromPath updates this.packagesJson
|
||||
@@ -168,7 +168,7 @@ export class ExtensionDiscovery extends Singleton {
|
||||
|
||||
if (extension) {
|
||||
// Remove a broken symlink left by a previous installation if it exists.
|
||||
await this.removeSymlinkByManifestPath(manifestPath);
|
||||
await fse.remove(extension.manifestPath);
|
||||
|
||||
// Install dependencies for the new extension
|
||||
await this.installPackage(extension.absolutePath);
|
||||
@@ -178,40 +178,46 @@ export class ExtensionDiscovery extends Singleton {
|
||||
this.events.emit("add", extension);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
logger.error(`${logModule}: failed to add extension: ${error}`, { error });
|
||||
} finally {
|
||||
ExtensionInstallationStateStore.clearInstallingFromMain(manifestPath);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleWatchUnlinkDir = async (filePath: string) => {
|
||||
// filePath is the non-symlinked path to the extension folder
|
||||
// this.packagesJson.dependencies value is the non-symlinked path to the extension folder
|
||||
// LensExtensionId in extension-loader is the symlinked path to the extension folder manifest file
|
||||
|
||||
/**
|
||||
* Handle any unlink event, filtering out non-package.json links so the delete code
|
||||
* only happens once per extension.
|
||||
* @param filePath The absolute path to either a folder or file in the extensions folder
|
||||
*/
|
||||
handleWatchUnlinkEvent = async (filePath: string): Promise<void> => {
|
||||
// Check that the removed path is directly under this.localFolderPath
|
||||
// Note that the watcher can create unlink events for subdirectories of the extension
|
||||
const extensionFolderName = path.basename(filePath);
|
||||
const expectedPath = path.relative(this.localFolderPath, filePath);
|
||||
|
||||
if (path.relative(this.localFolderPath, filePath) === extensionFolderName) {
|
||||
const extension = Array.from(this.extensions.values()).find((extension) => extension.absolutePath === filePath);
|
||||
|
||||
if (extension) {
|
||||
const extensionName = extension.manifest.name;
|
||||
|
||||
// If the extension is deleted manually while the application is running, also remove the symlink
|
||||
await this.removeSymlinkByPackageName(extensionName);
|
||||
|
||||
// The path to the manifest file is the lens extension id
|
||||
// Note that we need to use the symlinked path
|
||||
const lensExtensionId = extension.manifestPath;
|
||||
|
||||
this.extensions.delete(extension.id);
|
||||
logger.info(`${logModule} removed extension ${extensionName}`);
|
||||
this.events.emit("remove", lensExtensionId as LensExtensionId);
|
||||
} else {
|
||||
logger.warn(`${logModule} extension ${extensionFolderName} not found, can't remove`);
|
||||
}
|
||||
if (expectedPath !== extensionFolderName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const extension = Array.from(this.extensions.values()).find((extension) => extension.absolutePath === filePath);
|
||||
|
||||
if (!extension) {
|
||||
return void logger.warn(`${logModule} extension ${extensionFolderName} not found, can't remove`);
|
||||
}
|
||||
|
||||
const extensionName = extension.manifest.name;
|
||||
|
||||
// If the extension is deleted manually while the application is running, also remove the symlink
|
||||
await this.removeSymlinkByPackageName(extensionName);
|
||||
|
||||
// The path to the manifest file is the lens extension id
|
||||
// Note: that we need to use the symlinked path
|
||||
const lensExtensionId = extension.manifestPath;
|
||||
|
||||
this.extensions.delete(extension.id);
|
||||
logger.info(`${logModule} removed extension ${extensionName}`);
|
||||
this.events.emit("remove", lensExtensionId);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -221,31 +227,23 @@ export class ExtensionDiscovery extends Singleton {
|
||||
* @param name e.g. "@mirantis/lens-extension-cc"
|
||||
*/
|
||||
removeSymlinkByPackageName(name: string) {
|
||||
return fs.remove(this.getInstalledPath(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the symlink under node_modules if it exists.
|
||||
* @param manifestPath Path to package.json
|
||||
*/
|
||||
removeSymlinkByManifestPath(manifestPath: string) {
|
||||
const manifestJson = __non_webpack_require__(manifestPath);
|
||||
|
||||
return this.removeSymlinkByPackageName(manifestJson.name);
|
||||
return fse.remove(this.getInstalledPath(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstalls extension.
|
||||
* The application will detect the folder unlink and remove the extension from the UI automatically.
|
||||
* @param extension Extension to uninstall.
|
||||
* @param extensionId The ID of the extension to uninstall.
|
||||
*/
|
||||
async uninstallExtension({ absolutePath, manifest }: InstalledExtension) {
|
||||
async uninstallExtension(extensionId: LensExtensionId) {
|
||||
const { manifest, absolutePath } = this.extensions.get(extensionId) ?? ExtensionLoader.getInstance().getExtension(extensionId);
|
||||
|
||||
logger.info(`${logModule} Uninstalling ${manifest.name}`);
|
||||
|
||||
await this.removeSymlinkByPackageName(manifest.name);
|
||||
|
||||
// fs.remove does nothing if the path doesn't exist anymore
|
||||
await fs.remove(absolutePath);
|
||||
await fse.remove(absolutePath);
|
||||
}
|
||||
|
||||
async load(): Promise<Map<LensExtensionId, InstalledExtension>> {
|
||||
@@ -259,12 +257,11 @@ export class ExtensionDiscovery extends Singleton {
|
||||
logger.info(`${logModule} loading extensions from ${extensionInstaller.extensionPackagesRoot}`);
|
||||
|
||||
// fs.remove won't throw if path is missing
|
||||
await fs.remove(path.join(extensionInstaller.extensionPackagesRoot, "package-lock.json"));
|
||||
|
||||
await fse.remove(path.join(extensionInstaller.extensionPackagesRoot, "package-lock.json"));
|
||||
|
||||
try {
|
||||
// Verify write access to static/extensions, which is needed for symlinking
|
||||
await fs.access(this.inTreeFolderPath, fs.constants.W_OK);
|
||||
await fse.access(this.inTreeFolderPath, fse.constants.W_OK);
|
||||
|
||||
// Set bundled folder path to static/extensions
|
||||
this.bundledFolderPath = this.inTreeFolderPath;
|
||||
@@ -273,20 +270,20 @@ export class ExtensionDiscovery extends Singleton {
|
||||
// The error can happen if there is read-only rights to static/extensions, which would fail symlinking.
|
||||
|
||||
// Remove e.g. /Users/<username>/Library/Application Support/LensDev/extensions
|
||||
await fs.remove(this.inTreeTargetPath);
|
||||
await fse.remove(this.inTreeTargetPath);
|
||||
|
||||
// Create folder e.g. /Users/<username>/Library/Application Support/LensDev/extensions
|
||||
await fs.ensureDir(this.inTreeTargetPath);
|
||||
await fse.ensureDir(this.inTreeTargetPath);
|
||||
|
||||
// Copy static/extensions to e.g. /Users/<username>/Library/Application Support/LensDev/extensions
|
||||
await fs.copy(this.inTreeFolderPath, this.inTreeTargetPath);
|
||||
await fse.copy(this.inTreeFolderPath, this.inTreeTargetPath);
|
||||
|
||||
// Set bundled folder path to e.g. /Users/<username>/Library/Application Support/LensDev/extensions
|
||||
this.bundledFolderPath = this.inTreeTargetPath;
|
||||
}
|
||||
|
||||
await fs.ensureDir(this.nodeModulesPath);
|
||||
await fs.ensureDir(this.localFolderPath);
|
||||
await fse.ensureDir(this.nodeModulesPath);
|
||||
await fse.ensureDir(this.localFolderPath);
|
||||
|
||||
const extensions = await this.ensureExtensions();
|
||||
|
||||
@@ -315,30 +312,22 @@ export class ExtensionDiscovery extends Singleton {
|
||||
* Returns InstalledExtension from path to package.json file.
|
||||
* Also updates this.packagesJson.
|
||||
*/
|
||||
protected async getByManifest(manifestPath: string, { isBundled = false }: {
|
||||
isBundled?: boolean;
|
||||
} = {}): Promise<InstalledExtension | null> {
|
||||
let manifestJson: LensExtensionManifest;
|
||||
|
||||
protected async getByManifest(manifestPath: string, { isBundled = false } = {}): Promise<InstalledExtension | null> {
|
||||
try {
|
||||
// check manifest file for existence
|
||||
fs.accessSync(manifestPath, fs.constants.F_OK);
|
||||
|
||||
manifestJson = __non_webpack_require__(manifestPath);
|
||||
const installedManifestPath = this.getInstalledManifestPath(manifestJson.name);
|
||||
|
||||
const isEnabled = isBundled || ExtensionsStore.getInstance().isEnabled(installedManifestPath);
|
||||
const manifest = await fse.readJson(manifestPath);
|
||||
const installedManifestPath = this.getInstalledManifestPath(manifest.name);
|
||||
const isEnabled = isBundled || ExtensionsStore.getInstance().isEnabled(installedManifestPath);
|
||||
|
||||
return {
|
||||
id: installedManifestPath,
|
||||
absolutePath: path.dirname(manifestPath),
|
||||
manifestPath: installedManifestPath,
|
||||
manifest: manifestJson,
|
||||
manifest,
|
||||
isBundled,
|
||||
isEnabled
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error(`${logModule}: can't load extension manifest at ${manifestPath}: ${error}`, { manifestJson });
|
||||
logger.error(`${logModule}: can't load extension manifest at ${manifestPath}: ${error}`);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -352,7 +341,7 @@ export class ExtensionDiscovery extends Singleton {
|
||||
const userExtensions = await this.loadFromFolder(this.localFolderPath, bundledExtensions.map((extension) => extension.manifest.name));
|
||||
|
||||
for (const extension of userExtensions) {
|
||||
if (await fs.pathExists(extension.manifestPath) === false) {
|
||||
if (await fse.pathExists(extension.manifestPath) === false) {
|
||||
await this.installPackage(extension.absolutePath);
|
||||
}
|
||||
}
|
||||
@@ -383,7 +372,7 @@ export class ExtensionDiscovery extends Singleton {
|
||||
async loadBundledExtensions() {
|
||||
const extensions: InstalledExtension[] = [];
|
||||
const folderPath = this.bundledFolderPath;
|
||||
const paths = await fs.readdir(folderPath);
|
||||
const paths = await fse.readdir(folderPath);
|
||||
|
||||
for (const fileName of paths) {
|
||||
const absPath = path.resolve(folderPath, fileName);
|
||||
@@ -400,7 +389,7 @@ export class ExtensionDiscovery extends Singleton {
|
||||
|
||||
async loadFromFolder(folderPath: string, bundledExtensions: string[]): Promise<InstalledExtension[]> {
|
||||
const extensions: InstalledExtension[] = [];
|
||||
const paths = await fs.readdir(folderPath);
|
||||
const paths = await fse.readdir(folderPath);
|
||||
|
||||
for (const fileName of paths) {
|
||||
// do not allow to override bundled extensions
|
||||
@@ -410,11 +399,11 @@ export class ExtensionDiscovery extends Singleton {
|
||||
|
||||
const absPath = path.resolve(folderPath, fileName);
|
||||
|
||||
if (!fs.existsSync(absPath)) {
|
||||
if (!fse.existsSync(absPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const lstat = await fs.lstat(absPath);
|
||||
const lstat = await fse.lstat(absPath);
|
||||
|
||||
// skip non-directories
|
||||
if (!isDirectoryLike(lstat)) {
|
||||
|
||||
@@ -13,8 +13,6 @@ import type { LensExtension, LensExtensionConstructor, LensExtensionId } from ".
|
||||
import type { LensMainExtension } from "./lens-main-extension";
|
||||
import type { LensRendererExtension } from "./lens-renderer-extension";
|
||||
import * as registries from "./registries";
|
||||
import fs from "fs";
|
||||
|
||||
|
||||
export function extensionPackagesRoot() {
|
||||
return path.join((app || remote.app).getPath("userData"));
|
||||
@@ -290,28 +288,20 @@ export class ExtensionLoader extends Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
protected requireExtension(extension: InstalledExtension): LensExtensionConstructor {
|
||||
let extEntrypoint = "";
|
||||
protected requireExtension(extension: InstalledExtension): LensExtensionConstructor | null {
|
||||
const entryPointName = ipcRenderer ? "renderer" : "main";
|
||||
const extRelativePath = extension.manifest[entryPointName];
|
||||
|
||||
if (!extRelativePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const extAbsolutePath = path.resolve(path.join(path.dirname(extension.manifestPath), extRelativePath));
|
||||
|
||||
try {
|
||||
if (ipcRenderer && extension.manifest.renderer) {
|
||||
extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.renderer));
|
||||
} else if (!ipcRenderer && extension.manifest.main) {
|
||||
extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.main));
|
||||
}
|
||||
|
||||
if (extEntrypoint !== "") {
|
||||
if (!fs.existsSync(extEntrypoint)) {
|
||||
console.log(`${logModule}: entrypoint ${extEntrypoint} not found, skipping ...`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return __non_webpack_require__(extEntrypoint).default;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`${logModule}: can't load extension main at ${extEntrypoint}: ${err}`, { extension });
|
||||
console.trace(err);
|
||||
return __non_webpack_require__(extAbsolutePath).default;
|
||||
} catch (error) {
|
||||
logger.error(`${logModule}: can't load extension main at ${extAbsolutePath}: ${error}`, { extension, error });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,17 @@ export interface KubeObjectStatusRegistration {
|
||||
|
||||
export class KubeObjectStatusRegistry extends BaseRegistry<KubeObjectStatusRegistration> {
|
||||
getItemsForKind(kind: string, apiVersion: string) {
|
||||
return this.getItems().filter((item) => {
|
||||
return item.kind === kind && item.apiVersions.includes(apiVersion);
|
||||
});
|
||||
return this.getItems()
|
||||
.filter((item) => (
|
||||
item.kind === kind
|
||||
&& item.apiVersions.includes(apiVersion)
|
||||
));
|
||||
}
|
||||
|
||||
getItemsForObject(src: KubeObject) {
|
||||
return this.getItemsForKind(src.kind, src.apiVersion)
|
||||
.map(item => item.resolve(src))
|
||||
.filter(Boolean);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user