mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Allow extensions to define cluster features (#1125)
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
1 parent
f3a0059355
commit
62ae7771df
81 files changed
+4069
-510
No files matched your search
@@ -0,0 +1,62 @@
|
||||
import fs from "fs";
|
||||
import path from "path"
|
||||
import hb from "handlebars"
|
||||
import { observable } from "mobx"
|
||||
import { ResourceApplier } from "../main/resource-applier"
|
||||
import { Cluster } from "../main/cluster";
|
||||
import logger from "../main/logger";
|
||||
import { app } from "electron"
|
||||
import { clusterIpc } from "../common/cluster-ipc"
|
||||
|
||||
export interface ClusterFeatureStatus {
|
||||
currentVersion: string;
|
||||
installed: boolean;
|
||||
latestVersion: string;
|
||||
canUpgrade: boolean;
|
||||
}
|
||||
|
||||
export abstract class ClusterFeature {
|
||||
name: string;
|
||||
latestVersion: string;
|
||||
config: any;
|
||||
|
||||
@observable status: ClusterFeatureStatus = {
|
||||
currentVersion: null,
|
||||
installed: false,
|
||||
latestVersion: null,
|
||||
canUpgrade: false
|
||||
}
|
||||
|
||||
abstract async install(cluster: Cluster): Promise<void>;
|
||||
|
||||
abstract async upgrade(cluster: Cluster): Promise<void>;
|
||||
|
||||
abstract async uninstall(cluster: Cluster): Promise<void>;
|
||||
|
||||
abstract async updateStatus(cluster: Cluster): Promise<ClusterFeatureStatus>;
|
||||
|
||||
protected async applyResources(cluster: Cluster, resources: string[]) {
|
||||
if (app) {
|
||||
await new ResourceApplier(cluster).kubectlApplyAll(resources)
|
||||
} else {
|
||||
await clusterIpc.kubectlApplyAll.invokeFromRenderer(cluster.id, resources)
|
||||
}
|
||||
}
|
||||
|
||||
protected renderTemplates(folderPath: string): string[] {
|
||||
const resources: string[] = [];
|
||||
logger.info(`[FEATURE]: render templates from ${folderPath}`);
|
||||
fs.readdirSync(folderPath).forEach(filename => {
|
||||
const file = path.join(folderPath, filename);
|
||||
const raw = fs.readFileSync(file);
|
||||
if (filename.endsWith('.hb')) {
|
||||
const template = hb.compile(raw.toString());
|
||||
resources.push(template(this.config));
|
||||
} else {
|
||||
resources.push(raw.toString());
|
||||
}
|
||||
});
|
||||
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { ClusterFeature as Feature, ClusterFeatureStatus as FeatureStatus } from "../cluster-feature"
|
||||
@@ -10,11 +10,13 @@ import * as Store from "./stores"
|
||||
import * as Util from "./utils"
|
||||
import * as Registry from "../registries"
|
||||
import * as CommonVars from "../../common/vars";
|
||||
import * as ClusterFeature from "./cluster-feature"
|
||||
|
||||
export let windowManager: WindowManager;
|
||||
|
||||
export {
|
||||
EventBus,
|
||||
ClusterFeature,
|
||||
Store,
|
||||
Util,
|
||||
Registry,
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { ExtensionStore } from "../extension-store"
|
||||
export type { Cluster } from "../../main/cluster"
|
||||
@@ -0,0 +1,19 @@
|
||||
// Lens-extensions api developer's kit
|
||||
export type { LensExtensionRuntimeEnv } from "./lens-runtime";
|
||||
export * from "./lens-main-extension"
|
||||
export * from "./lens-renderer-extension"
|
||||
|
||||
// APIs
|
||||
import * as EventBus from "./core-api/event-bus"
|
||||
import * as Store from "./core-api/stores"
|
||||
import * as Util from "./core-api/utils"
|
||||
import * as Registry from "./core-api/registries"
|
||||
import * as ClusterFeature from "./core-api/cluster-feature"
|
||||
|
||||
export {
|
||||
ClusterFeature,
|
||||
EventBus,
|
||||
Registry,
|
||||
Store,
|
||||
Util
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import { broadcastIpc } from "../common/ipc"
|
||||
import { observable, reaction, toJS, } from "mobx"
|
||||
import logger from "../main/logger"
|
||||
import { app, ipcRenderer, remote } from "electron"
|
||||
import { appPreferenceRegistry, kubeObjectMenuRegistry, menuRegistry, pageRegistry, statusBarRegistry } from "./registries";
|
||||
import { appPreferenceRegistry, kubeObjectMenuRegistry, menuRegistry, pageRegistry, statusBarRegistry, clusterFeatureRegistry } from "./registries";
|
||||
|
||||
export interface InstalledExtension extends ExtensionModel {
|
||||
manifestPath: string;
|
||||
@@ -46,6 +46,7 @@ export class ExtensionLoader {
|
||||
this.autoloadExtensions((instance: LensRendererExtension) => {
|
||||
instance.registerPages(pageRegistry)
|
||||
instance.registerAppPreferences(appPreferenceRegistry)
|
||||
instance.registerClusterFeatures(clusterFeatureRegistry)
|
||||
instance.registerStatusBarIcon(statusBarRegistry)
|
||||
})
|
||||
}
|
||||
@@ -60,8 +61,8 @@ export class ExtensionLoader {
|
||||
|
||||
protected autoloadExtensions(callback: (instance: LensExtension) => void) {
|
||||
return reaction(() => this.extensions.toJS(), (installedExtensions) => {
|
||||
for (const [id, ext] of installedExtensions) {
|
||||
let instance = this.instances.get(ext.name)
|
||||
for(const [id, ext] of installedExtensions) {
|
||||
let instance = this.instances.get(ext.id)
|
||||
if (!instance) {
|
||||
const extensionModule = this.requireExtension(ext)
|
||||
if (!extensionModule) {
|
||||
@@ -69,9 +70,12 @@ export class ExtensionLoader {
|
||||
}
|
||||
const LensExtensionClass = extensionModule.default;
|
||||
instance = new LensExtensionClass({ ...ext.manifest, manifestPath: ext.manifestPath, id: ext.manifestPath }, ext.manifest);
|
||||
instance.enable();
|
||||
callback(instance)
|
||||
this.instances.set(ext.name, instance)
|
||||
try {
|
||||
instance.enable()
|
||||
callback(instance)
|
||||
} finally {
|
||||
this.instances.set(ext.id, instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { LensExtension } from "./lens-extension"
|
||||
import type { PageRegistry, AppPreferenceRegistry, StatusBarRegistry, KubeObjectMenuRegistry } from "./registries"
|
||||
import type { PageRegistry, AppPreferenceRegistry, StatusBarRegistry, KubeObjectMenuRegistry, ClusterFeatureRegistry } from "./registries"
|
||||
|
||||
export class LensRendererExtension extends LensExtension {
|
||||
registerPages(registry: PageRegistry) {
|
||||
@@ -10,6 +10,10 @@ export class LensRendererExtension extends LensExtension {
|
||||
return
|
||||
}
|
||||
|
||||
registerClusterFeatures(registry: ClusterFeatureRegistry) {
|
||||
return
|
||||
}
|
||||
|
||||
registerStatusBarIcon(registry: StatusBarRegistry) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { BaseRegistry } from "./base-registry";
|
||||
import { ClusterFeature } from "../cluster-feature";
|
||||
|
||||
export interface ClusterFeatureComponents {
|
||||
Description: React.ComponentType<any>;
|
||||
}
|
||||
|
||||
export interface ClusterFeatureRegistration {
|
||||
title: string;
|
||||
components: ClusterFeatureComponents
|
||||
feature: ClusterFeature
|
||||
}
|
||||
|
||||
export class ClusterFeatureRegistry extends BaseRegistry<ClusterFeatureRegistration> {}
|
||||
|
||||
export const clusterFeatureRegistry = new ClusterFeatureRegistry()
|
||||
@@ -5,3 +5,4 @@ export * from "./menu-registry"
|
||||
export * from "./app-preference-registry"
|
||||
export * from "./status-bar-registry"
|
||||
export * from "./kube-object-menu-registry";
|
||||
export * from "./cluster-feature-registry"
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
export { apiManager } from "../../renderer/api/api-manager";
|
||||
export { KubeApi } from "../../renderer/api/kube-api";
|
||||
export { KubeApi, forCluster, IKubeApiCluster } from "../../renderer/api/kube-api";
|
||||
export { KubeObject } from "../../renderer/api/kube-object";
|
||||
export { Pod, podsApi, IPodContainer, IPodContainerStatus } from "../../renderer/api/endpoints";
|
||||
export { Node, nodesApi } from "../../renderer/api/endpoints";
|
||||
|
||||
Reference in new issue
Block a user