1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

more work

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-02-18 09:00:02 -05:00
parent d6177a64f2
commit 0660d74dad
5 changed files with 37 additions and 44 deletions

View File

@ -43,9 +43,9 @@ export class ExtensionInstaller {
mode: 0o600 mode: 0o600
}); });
logger.info(`${logModule} installing dependencies at ${extensionPackagesRoot()}`); logger.info(`${logModule}: installing dependencies at ${this.extensionPackagesRoot}`);
await this.npm(["install", "--no-audit", "--only=prod", "--prefer-offline", "--no-package-lock"]); await this.npm(["install", "--no-audit", "--only=prod", "--prefer-offline", "--no-package-lock"]);
logger.info(`${logModule} dependencies installed at ${extensionPackagesRoot()}`); logger.info(`${logModule}: dependencies installed at ${this.extensionPackagesRoot}`);
} finally { } finally {
this.installLock.release(); this.installLock.release();
} }
@ -59,9 +59,9 @@ export class ExtensionInstaller {
await this.installLock.acquireAsync(); await this.installLock.acquireAsync();
try { try {
logger.info(`${logModule} installing package from ${name} to ${extensionPackagesRoot()}`); logger.info(`${logModule}: installing package from ${name} to ${this.extensionPackagesRoot}`);
await this.npm(["install", "--no-audit", "--only=prod", "--prefer-offline", "--no-package-lock", "--no-save", name]); await this.npm(["install", "--no-audit", "--only=prod", "--prefer-offline", "--no-package-lock", "--no-save", name]);
logger.info(`${logModule} package ${name} installed to ${extensionPackagesRoot()}`); logger.info(`${logModule}: package ${name} installed to ${this.extensionPackagesRoot}`);
} finally { } finally {
this.installLock.release(); this.installLock.release();
} }
@ -70,7 +70,7 @@ export class ExtensionInstaller {
private npm(args: string[]): Promise<void> { private npm(args: string[]): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const child = child_process.fork(this.npmPath, args, { const child = child_process.fork(this.npmPath, args, {
cwd: extensionPackagesRoot(), cwd: this.extensionPackagesRoot,
silent: true, silent: true,
env: {} env: {}
}); });

View File

@ -13,6 +13,7 @@ import type { LensMainExtension } from "./lens-main-extension";
import type { LensRendererExtension } from "./lens-renderer-extension"; import type { LensRendererExtension } from "./lens-renderer-extension";
import * as registries from "./registries"; import * as registries from "./registries";
import fs from "fs"; import fs from "fs";
import { delay } from "../common/utils";
// lazy load so that we get correct userData // lazy load so that we get correct userData
export function extensionPackagesRoot() { export function extensionPackagesRoot() {
@ -87,7 +88,7 @@ export class ExtensionLoader {
this.extensions.set(extension.id, extension); this.extensions.set(extension.id, extension);
} }
removeInstance(lensExtensionId: LensExtensionId) { async removeInstance(lensExtensionId: LensExtensionId) {
logger.info(`${logModule} deleting extension instance ${lensExtensionId}`); logger.info(`${logModule} deleting extension instance ${lensExtensionId}`);
const instance = this.instances.get(lensExtensionId); const instance = this.instances.get(lensExtensionId);
@ -96,13 +97,12 @@ export class ExtensionLoader {
} }
try { try {
instance.disable(); await Promise.race([instance.disable(), delay(15 * 1000)]); // allow at most 15s to disable the instace
this.events.emit("remove", instance); this.events.emit("remove", instance);
this.instances.delete(lensExtensionId); this.instances.delete(lensExtensionId);
} catch (error) { } catch (error) {
logger.error(`${logModule}: deactivation extension error`, { lensExtensionId, error }); logger.error(`${logModule}: deactivation extension error`, { lensExtensionId, error });
} }
} }
removeExtension(lensExtensionId: LensExtensionId) { removeExtension(lensExtensionId: LensExtensionId) {

View File

@ -57,7 +57,7 @@ export class LensExtension {
async enable() { async enable() {
if (this.isEnabled) return; if (this.isEnabled) return;
this.isEnabled = true; this.isEnabled = true;
this.onActivate(); await this.onActivate();
logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`); logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`);
} }
@ -65,7 +65,7 @@ export class LensExtension {
async disable() { async disable() {
if (!this.isEnabled) return; if (!this.isEnabled) return;
this.isEnabled = false; this.isEnabled = false;
this.onDeactivate(); await this.onDeactivate();
logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`); logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`);
} }
@ -101,11 +101,11 @@ export class LensExtension {
}; };
} }
protected onActivate() { protected onActivate(): Promise<void> | void {
// mock // mock
} }
protected onDeactivate() { protected onDeactivate(): Promise<void> | void {
// mock // mock
} }
} }

View File

@ -12,11 +12,9 @@ type CachedYaml = {
export class HelmChartManager { export class HelmChartManager {
protected cache: any = {}; protected cache: any = {};
protected repo: HelmRepo;
constructor(repo: HelmRepo){ constructor(protected repo: HelmRepo){
this.cache = HelmRepoManager.cache; this.cache = HelmRepoManager.cache;
this.repo = repo;
} }
public async chart(name: string) { public async chart(name: string) {

View File

@ -46,6 +46,10 @@ function parseLensExtensionManifest(buf: Buffer): LensExtensionManifest {
return raw; return raw;
} }
function notifyOnAction(displayName: string, action: string): void {
Notifications.ok(<p>Extension <b>{displayName}</b> successfully {action}!</p>);
}
@observer @observer
export class Extensions extends React.Component { export class Extensions extends React.Component {
private static supportedFormats = ["tar", "tgz"]; private static supportedFormats = ["tar", "tgz"];
@ -95,9 +99,7 @@ export class Extensions extends React.Component {
disposeOnUnmount(this, disposeOnUnmount(this,
reaction(() => this.extensions, () => { reaction(() => this.extensions, () => {
this.removedUninstalling.forEach(({ id, displayName }) => { this.removedUninstalling.forEach(({ id, displayName }) => {
Notifications.ok( notifyOnAction(displayName, "uninstalled");
<p>Extension <b>{displayName}</b> successfully uninstalled!</p>
);
this.extensionStateStore.extensionState.delete(id); this.extensionStateStore.extensionState.delete(id);
}); });
@ -108,9 +110,7 @@ export class Extensions extends React.Component {
throw new Error("Extension not found"); throw new Error("Extension not found");
} }
Notifications.ok( notifyOnAction(displayName, "installed");
<p>Extension <b>{displayName}</b> successfully installed!</p>
);
this.extensionStateStore.extensionState.delete(id); this.extensionStateStore.extensionState.delete(id);
this.installPath = ""; this.installPath = "";
@ -205,39 +205,36 @@ export class Extensions extends React.Component {
); );
}; };
async preloadExtensions(requests: InstallRequest[], { showError = true } = {}) { async preloadExtensions(requests: InstallRequest[], { showError = true } = {}): Promise<InstallRequestPreloaded[]> {
const preloadedRequests = requests.filter(request => request.data); const res = await Promise.all(
requests.map(async ({ data, fileName, filePath }) => {
if (data) {
return { data, fileName, filePath };
}
await Promise.all( if (filePath) {
requests
.filter(request => !request.data && request.filePath)
.map(async request => {
try { try {
const data = await fse.readFile(request.filePath); return { data: await fse.readFile(filePath), fileName, filePath };
request.data = data;
preloadedRequests.push(request);
return request;
} catch(error) { } catch(error) {
if (showError) { if (showError) {
Notifications.error(`Error while reading "${request.filePath}": ${String(error)}`); Notifications.error(`Error while reading "${filePath}": ${String(error)}`);
} }
} }
}) }
})
); );
return preloadedRequests as InstallRequestPreloaded[]; return res.filter(Boolean);
} }
async validatePackage(filePath: string): Promise<LensExtensionManifest> { async validatePackage(filePath: string): Promise<LensExtensionManifest> {
const tarFiles = await listTarEntries(filePath); const tarFiles = await listTarEntries(filePath);
// tarball from npm contains single root folder "package/*" // tarball from npm contains single root folder "package/*"
const firstFile = tarFiles[0]; const [firstFile] = tarFiles;
if (!firstFile) { if (!firstFile) {
throw new Error(`invalid extension bundle, ${manifestFilename} not found`); throw new Error(`invalid extension bundle, ${manifestFilename} not found`);
} }
const rootFolder = path.normalize(firstFile).split(path.sep)[0]; const rootFolder = path.normalize(firstFile).split(path.sep)[0];
@ -255,7 +252,7 @@ export class Extensions extends React.Component {
}); });
if (!manifest.lens && !manifest.renderer) { if (!manifest.lens && !manifest.renderer) {
throw new Error(`${manifestFilename} must specify "main" and/or "renderer" fields`); throw new Error(`${manifestFilename} must specify at least one of: ["main", "renderer"]`);
} }
return manifest; return manifest;
@ -267,11 +264,9 @@ export class Extensions extends React.Component {
// copy files to temp // copy files to temp
await fse.ensureDir(this.getExtensionPackageTemp()); await fse.ensureDir(this.getExtensionPackageTemp());
for (const request of requests) { await Promise.all(
const tempFile = this.getExtensionPackageTemp(request.fileName); requests.map(request => fse.writeFile(this.getExtensionPackageTemp(request.fileName), request.data))
);
await fse.writeFile(tempFile, request.data);
}
// validate packages // validate packages
await Promise.all( await Promise.all(