Cleanup 'Cluster' to remove environment specific details (#6951)

- requestNamespaceListPermissions is infallable so no need to have the extra try/catch

- Refactor isMetricHidden method away from Cluster

- Refactor shouldShowResource out of Cluster

- Refactor isInLocalKubeconfig out of Cluster

- Remove depecrated and unused workspace from Cluster

- Refactor out kubectl as a dependency of Cluster

- Remove from cluster getter used only once

- Split out ClusterConnection from Cluster

- Also split out KubeAuthProxyServer from ContextHandler

- Rename ContextHandler to PrometheusHandler

- Cleanup onNetworkOffline/Online impls within ClusterManager

- Remove annotations from ClusterConnection

- Remove mobx annotations from Cluster

- Rename loadConfigFromFileInjectable

- Remove all uses of dead createClusterInjectionToken

- Fix type errors related to broadcastConnectionUpdate

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton authored and GitHub committed 2023-03-10 09:37:39 +02:00
1 parent e6d6d1d8f7
commit ad9bafe2a5
133 files changed
+2544 -1961

No files matched your search

@@ -2,44 +2,43 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import type { Cluster } from "../../common/cluster/cluster";
import directoryForTempInjectable from "../../common/app-paths/directory-for-temp/directory-for-temp.injectable";
import type { KubeconfigManagerDependencies } from "./kubeconfig-manager";
import { KubeconfigManager } from "./kubeconfig-manager";
import loggerInjectable from "../../common/logger.injectable";
import lensProxyPortInjectable from "../lens-proxy/lens-proxy-port.injectable";
import joinPathsInjectable from "../../common/path/join-paths.injectable";
import getDirnameOfPathInjectable from "../../common/path/get-dirname.injectable";
import pathExistsInjectable from "../../common/fs/path-exists.injectable";
import writeFileInjectable from "../../common/fs/write-file.injectable";
import removePathInjectable from "../../common/fs/remove.injectable";
import lensProxyCertificateInjectable from "../../common/certificate/lens-proxy-certificate.injectable";
import kubeAuthProxyServerInjectable from "../cluster/kube-auth-proxy-server.injectable";
import kubeAuthProxyUrlInjectable from "../cluster/auth-proxy-url.injectable";
import loadKubeconfigInjectable from "../../common/cluster/load-kubeconfig.injectable";
export interface KubeConfigManagerInstantiationParameter {
cluster: Cluster;
}
const kubeconfigManagerInjectable = getInjectable({
id: "kubeconfig-manager",
export type CreateKubeconfigManager = (cluster: Cluster) => KubeconfigManager;
const createKubeconfigManagerInjectable = getInjectable({
id: "create-kubeconfig-manager",
instantiate: (di): CreateKubeconfigManager => {
const dependencies: KubeconfigManagerDependencies = {
instantiate: (di, cluster) => new KubeconfigManager(
{
directoryForTemp: di.inject(directoryForTempInjectable),
logger: di.inject(loggerInjectable),
lensProxyPort: di.inject(lensProxyPortInjectable),
joinPaths: di.inject(joinPathsInjectable),
getDirnameOfPath: di.inject(getDirnameOfPathInjectable),
removePath: di.inject(removePathInjectable),
pathExists: di.inject(pathExistsInjectable),
writeFile: di.inject(writeFileInjectable),
certificate: di.inject(lensProxyCertificateInjectable).get(),
};
return (cluster) => new KubeconfigManager(dependencies, cluster);
},
loadKubeconfig: di.inject(loadKubeconfigInjectable, cluster),
kubeAuthProxyServer: di.inject(kubeAuthProxyServerInjectable, cluster),
kubeAuthProxyUrl: di.inject(kubeAuthProxyUrlInjectable, cluster),
},
cluster,
),
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di, cluster: Cluster) => cluster.id,
}),
});
export default createKubeconfigManagerInjectable;
export default kubeconfigManagerInjectable;
@@ -4,8 +4,6 @@
*/
import type { KubeConfig } from "@kubernetes/client-node";
import type { Cluster } from "../../common/cluster/cluster";
import type { ClusterContextHandler } from "../context-handler/context-handler";
import { dumpConfigYaml } from "../../common/kube-helpers";
import { isErrnoException } from "../../common/utils";
import type { PartialDeep } from "type-fest";
@@ -16,17 +14,22 @@ import type { PathExists } from "../../common/fs/path-exists.injectable";
import type { RemovePath } from "../../common/fs/remove.injectable";
import type { WriteFile } from "../../common/fs/write-file.injectable";
import type { SelfSignedCert } from "selfsigned";
import type { Cluster } from "../../common/cluster/cluster";
import type { LoadKubeconfig } from "../../common/cluster/load-kubeconfig.injectable";
import type { KubeAuthProxyServer } from "../cluster/kube-auth-proxy-server.injectable";
export interface KubeconfigManagerDependencies {
interface KubeconfigManagerDependencies {
readonly directoryForTemp: string;
readonly logger: Logger;
readonly lensProxyPort: { get: () => number };
readonly certificate: SelfSignedCert;
readonly kubeAuthProxyServer: KubeAuthProxyServer;
readonly kubeAuthProxyUrl: string;
joinPaths: JoinPaths;
getDirnameOfPath: GetDirnameOfPath;
pathExists: PathExists;
removePath: RemovePath;
writeFile: WriteFile;
certificate: SelfSignedCert;
loadKubeconfig: LoadKubeconfig;
}
export class KubeconfigManager {
@@ -38,17 +41,16 @@ export class KubeconfigManager {
*/
protected tempFilePath: string | null = null;
protected readonly contextHandler: ClusterContextHandler;
constructor(private readonly dependencies: KubeconfigManagerDependencies, protected cluster: Cluster) {
this.contextHandler = cluster.contextHandler;
}
constructor(
private readonly dependencies: KubeconfigManagerDependencies,
private readonly cluster: Cluster,
) {}
/**
*
* @returns The path to the temporary kubeconfig
*/
async getPath(): Promise<string> {
async ensurePath(): Promise<string> {
if (this.tempFilePath === null || !(await this.dependencies.pathExists(this.tempFilePath))) {
return await this.ensureFile();
}
@@ -79,7 +81,7 @@ export class KubeconfigManager {
protected async ensureFile() {
try {
await this.contextHandler.ensureServer();
await this.dependencies.kubeAuthProxyServer.ensureRunning();
return this.tempFilePath = await this.createProxyKubeconfig();
} catch (error) {
@@ -87,31 +89,26 @@ export class KubeconfigManager {
}
}
get resolveProxyUrl() {
return `https://127.0.0.1:${this.dependencies.lensProxyPort.get()}/${this.cluster.id}`;
}
/**
* Creates new "temporary" kubeconfig that point to the kubectl-proxy.
* This way any user of the config does not need to know anything about the auth etc. details.
*/
protected async createProxyKubeconfig(): Promise<string> {
const { cluster } = this;
const { contextName, id } = cluster;
const { id, preferences: { defaultNamespace }} = this.cluster;
const contextName = this.cluster.contextName.get();
const tempFile = this.dependencies.joinPaths(
this.dependencies.directoryForTemp,
`kubeconfig-${id}`,
);
const kubeConfig = await cluster.getKubeconfig();
const { certificate } = this.dependencies;
const kubeConfig = await this.dependencies.loadKubeconfig();
const proxyConfig: PartialDeep<KubeConfig> = {
currentContext: contextName,
clusters: [
{
name: contextName,
server: this.resolveProxyUrl,
server: this.dependencies.kubeAuthProxyUrl,
skipTLSVerify: false,
caData: Buffer.from(certificate.cert).toString("base64"),
caData: Buffer.from(this.dependencies.certificate.cert).toString("base64"),
},
],
users: [
@@ -122,7 +119,7 @@ export class KubeconfigManager {
user: "proxy",
name: contextName,
cluster: contextName,
namespace: cluster.defaultNamespace || kubeConfig.getContextObject(contextName)?.namespace,
namespace: defaultNamespace || kubeConfig.getContextObject(contextName)?.namespace,
},
],
};