Allow extensions to define cluster features (#1125)

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen authored and GitHub committed 2020-10-26 08:21:22 +02:00
1 parent f3a0059355
commit 62ae7771df
81 files changed
+4069 -510

No files matched your search

+62
View File
@@ -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"
+2
View File
@@ -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
View File
@@ -1 +1,2 @@
export { ExtensionStore } from "../extension-store"
export type { Cluster } from "../../main/cluster"
+19
View File
@@ -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
}
+10 -6
View File
@@ -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)
}
}
}
}, {
+5 -1
View File
@@ -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()
+1
View File
@@ -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 -2
View File
@@ -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";