mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
convert the cluster settings view from Vue to React (#613)
- Add a basic file picker component - Now stores the icons as base64 img src formatted data blobs - Changed over cluster settings to mobx - Removed old Vue files Signed-off-by: Sebastian Malton <smalton@mirantis.com> Co-authored-by: Sebastian Malton <smalton@mirantis.com>
This commit is contained in:
1 parent
bac6fbaaf1
commit
d4ff99f3bf
41 files changed
+1375
-209
No files matched your search
@@ -34,6 +34,9 @@ export class ClusterManager {
|
||||
// listen for ipc-events that must/can be handled *only* in main-process (nodeIntegration=true)
|
||||
clusterIpc.activate.handleInMain();
|
||||
clusterIpc.disconnect.handleInMain();
|
||||
clusterIpc.installFeature.handleInMain();
|
||||
clusterIpc.uninstallFeature.handleInMain();
|
||||
clusterIpc.upgradeFeature.handleInMain();
|
||||
}
|
||||
|
||||
stop() {
|
||||
|
||||
+4
-4
@@ -136,7 +136,7 @@ export class Cluster implements ClusterModel {
|
||||
|
||||
async reconnect() {
|
||||
logger.info(`[CLUSTER]: reconnect`, this.getMeta());
|
||||
await this.contextHandler.stopServer();
|
||||
this.contextHandler.stopServer();
|
||||
await this.contextHandler.ensureServer();
|
||||
this.disconnected = false;
|
||||
}
|
||||
@@ -206,15 +206,15 @@ export class Cluster implements ClusterModel {
|
||||
}
|
||||
|
||||
async installFeature(name: string, config: any) {
|
||||
return await installFeature(name, this, config)
|
||||
return installFeature(name, this, config)
|
||||
}
|
||||
|
||||
async upgradeFeature(name: string, config: any) {
|
||||
return await upgradeFeature(name, this, config)
|
||||
return upgradeFeature(name, this, config)
|
||||
}
|
||||
|
||||
async uninstallFeature(name: string) {
|
||||
return await uninstallFeature(name, this)
|
||||
return uninstallFeature(name, this)
|
||||
}
|
||||
|
||||
getPrometheusApiPrefix() {
|
||||
|
||||
+24
-35
@@ -1,55 +1,44 @@
|
||||
import { KubeConfig } from "@kubernetes/client-node"
|
||||
import logger from "./logger";
|
||||
import { Cluster } from "./cluster";
|
||||
import { Feature, FeatureStatusMap } from "./feature"
|
||||
import { Feature, FeatureStatusMap, FeatureMap } from "./feature"
|
||||
import { MetricsFeature } from "../features/metrics"
|
||||
import { UserModeFeature } from "../features/user-mode"
|
||||
|
||||
const ALL_FEATURES: any = {
|
||||
'metrics': new MetricsFeature(null),
|
||||
'user-mode': new UserModeFeature(null),
|
||||
}
|
||||
const ALL_FEATURES: Map<string, Feature> = new Map([
|
||||
[MetricsFeature.id, new MetricsFeature(null)],
|
||||
[UserModeFeature.id, new UserModeFeature(null)],
|
||||
]);
|
||||
|
||||
export async function getFeatures(cluster: Cluster): Promise<FeatureStatusMap> {
|
||||
return new Promise<FeatureStatusMap>(async (resolve, reject) => {
|
||||
const result: FeatureStatusMap = {};
|
||||
logger.debug(`features for ${cluster.contextName}`);
|
||||
for (const key in ALL_FEATURES) {
|
||||
logger.debug(`feature ${key}`);
|
||||
if (ALL_FEATURES.hasOwnProperty(key)) {
|
||||
logger.debug("getting feature status...");
|
||||
const feature = ALL_FEATURES[key] as Feature;
|
||||
const kc = new KubeConfig()
|
||||
kc.loadFromFile(cluster.getProxyKubeconfigPath())
|
||||
|
||||
const status = await feature.featureStatus(kc);
|
||||
result[feature.name] = status
|
||||
const result: FeatureStatusMap = {};
|
||||
logger.debug(`features for ${cluster.contextName}`);
|
||||
|
||||
} else {
|
||||
logger.error("ALL_FEATURES.hasOwnProperty(key) returned FALSE ?!?!?!?!")
|
||||
for (const [key, feature] of ALL_FEATURES) {
|
||||
logger.debug(`feature ${key}`);
|
||||
logger.debug("getting feature status...");
|
||||
|
||||
}
|
||||
}
|
||||
logger.debug(`getFeatures resolving with features: ${JSON.stringify(result)}`);
|
||||
resolve(result);
|
||||
});
|
||||
const kc = new KubeConfig();
|
||||
kc.loadFromFile(cluster.getProxyKubeconfigPath());
|
||||
|
||||
result[feature.name] = await feature.featureStatus(kc);
|
||||
}
|
||||
|
||||
logger.debug(`getFeatures resolving with features: ${JSON.stringify(result)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
export async function installFeature(name: string, cluster: Cluster, config: any) {
|
||||
const feature = ALL_FEATURES[name] as Feature
|
||||
export async function installFeature(name: string, cluster: Cluster, config: any): Promise<void> {
|
||||
// TODO Figure out how to handle config stuff
|
||||
await feature.install(cluster)
|
||||
return ALL_FEATURES.get(name).install(cluster)
|
||||
}
|
||||
|
||||
export async function upgradeFeature(name: string, cluster: Cluster, config: any) {
|
||||
const feature = ALL_FEATURES[name] as Feature
|
||||
export async function upgradeFeature(name: string, cluster: Cluster, config: any): Promise<void> {
|
||||
// TODO Figure out how to handle config stuff
|
||||
await feature.upgrade(cluster)
|
||||
return ALL_FEATURES.get(name).upgrade(cluster)
|
||||
}
|
||||
|
||||
export async function uninstallFeature(name: string, cluster: Cluster) {
|
||||
const feature = ALL_FEATURES[name] as Feature
|
||||
|
||||
await feature.uninstall(cluster)
|
||||
export async function uninstallFeature(name: string, cluster: Cluster): Promise<void> {
|
||||
return ALL_FEATURES.get(name).uninstall(cluster)
|
||||
}
|
||||
+5
-5
@@ -7,6 +7,7 @@ import { Cluster } from "./cluster";
|
||||
import logger from "./logger";
|
||||
|
||||
export type FeatureStatusMap = Record<string, FeatureStatus>
|
||||
export type FeatureMap = Record<string, Feature>
|
||||
|
||||
export interface FeatureInstallRequest {
|
||||
clusterId: string;
|
||||
@@ -25,23 +26,22 @@ export abstract class Feature {
|
||||
name: string;
|
||||
latestVersion: string;
|
||||
|
||||
abstract async upgrade(cluster: Cluster): Promise<boolean>;
|
||||
abstract async upgrade(cluster: Cluster): Promise<void>;
|
||||
|
||||
abstract async uninstall(cluster: Cluster): Promise<boolean>;
|
||||
abstract async uninstall(cluster: Cluster): Promise<void>;
|
||||
|
||||
abstract async featureStatus(kc: KubeConfig): Promise<FeatureStatus>;
|
||||
|
||||
constructor(public config: any) {
|
||||
}
|
||||
|
||||
async install(cluster: Cluster): Promise<boolean> {
|
||||
async install(cluster: Cluster): Promise<void> {
|
||||
const resources = this.renderTemplates();
|
||||
try {
|
||||
await new ResourceApplier(cluster).kubectlApplyAll(resources);
|
||||
return true;
|
||||
} catch (err) {
|
||||
logger.error("Installing feature error", { err, cluster });
|
||||
return false
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,25 +31,30 @@ export class KubeAuthProxy {
|
||||
return;
|
||||
}
|
||||
const proxyBin = await this.kubectl.getPath()
|
||||
let args = [
|
||||
const args = [
|
||||
"proxy",
|
||||
"-p", this.port.toString(),
|
||||
"--kubeconfig", this.cluster.kubeConfigPath,
|
||||
"--context", this.cluster.contextName,
|
||||
"-p", `${this.port}`,
|
||||
// "--kubeconfig", `"${this.cluster.kubeConfigPath}"`,
|
||||
// "--context", `"${this.cluster.contextName}"`,
|
||||
"--kubeconfig", `${this.cluster.kubeConfigPath}`,
|
||||
"--context", `${this.cluster.contextName}`,
|
||||
"--accept-hosts", ".*",
|
||||
"--reject-paths", "^[^/]"
|
||||
]
|
||||
if (process.env.DEBUG_PROXY === "true") {
|
||||
args = args.concat(["-v", "9"])
|
||||
args.push("-v", "9")
|
||||
}
|
||||
logger.debug(`spawning kubectl proxy with args: ${args}`)
|
||||
this.proxyProcess = spawn(proxyBin, args, {
|
||||
env: this.env
|
||||
})
|
||||
this.proxyProcess = spawn(proxyBin, args, { env: this.env, })
|
||||
|
||||
this.proxyProcess.on("exit", (code) => {
|
||||
this.sendIpcLogMessage({ data: `proxy exited with code: ${code}`, error: code > 0 })
|
||||
this.proxyProcess = null
|
||||
this.proxyProcess.removeAllListeners();
|
||||
this.proxyProcess.stderr.removeAllListeners();
|
||||
this.proxyProcess.stdout.removeAllListeners();
|
||||
this.proxyProcess = null;
|
||||
})
|
||||
|
||||
this.proxyProcess.stdout.on('data', (data) => {
|
||||
let logItem = data.toString()
|
||||
if (logItem.startsWith("Starting to serve on")) {
|
||||
@@ -57,6 +62,7 @@ export class KubeAuthProxy {
|
||||
}
|
||||
this.sendIpcLogMessage({ data: logItem })
|
||||
})
|
||||
|
||||
this.proxyProcess.stderr.on('data', (data) => {
|
||||
this.lastError = this.parseError(data.toString())
|
||||
this.sendIpcLogMessage({ data: data.toString(), error: true })
|
||||
|
||||
@@ -25,7 +25,7 @@ export class ResourceApplier {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const fileName = tempy.file({ name: "resource.yaml" })
|
||||
fs.writeFileSync(fileName, content)
|
||||
const cmd = `"${kubectlPath}" apply --kubeconfig "${kubeConfigPath}" -o json -f ${fileName}`
|
||||
const cmd = `"${kubectlPath}" apply --kubeconfig "${kubeConfigPath}" -o json -f "${fileName}"`
|
||||
logger.debug("shooting manifests with: " + cmd);
|
||||
const execEnv: NodeJS.ProcessEnv = Object.assign({}, process.env)
|
||||
const httpsProxy = this.cluster.preferences?.httpsProxy
|
||||
@@ -54,7 +54,7 @@ export class ResourceApplier {
|
||||
resources.forEach((resource, index) => {
|
||||
fs.writeFileSync(path.join(tmpDir, `${index}.yaml`), resource);
|
||||
})
|
||||
const cmd = `"${kubectlPath}" apply --kubeconfig "${kubeConfigPath}" -o json -f ${tmpDir}`
|
||||
const cmd = `"${kubectlPath}" apply --kubeconfig "${kubeConfigPath}" -o json -f "${tmpDir}"`
|
||||
console.log("shooting manifests with:", cmd);
|
||||
exec(cmd, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
|
||||
Reference in new issue
Block a user