1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
lens/src/main/context-handler.ts
Jari Kolehmainen 1aaa695cfe
Refactor dashboard server logic to electron main (#146)
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
2020-03-24 07:37:47 +02:00

177 lines
5.1 KiB
TypeScript

import { KubeConfig } from "@kubernetes/client-node"
import { readFileSync } from "fs"
import * as http from "http"
import { ServerOptions } from "http-proxy"
import * as url from "url"
import logger from "./logger"
import { getFreePort } from "./port"
import { KubeAuthProxy } from "./kube-auth-proxy"
import { Cluster, ClusterPreferences } from "./cluster"
export class ContextHandler {
public contextName: string
public id: string
public url: string
public kc: KubeConfig
public certData: string
public authCertData: string
public cluster: Cluster
protected apiTarget: ServerOptions
protected proxyTarget: ServerOptions
protected clusterUrl: url.UrlWithStringQuery
protected proxyServer: KubeAuthProxy
protected clientCert: string
protected clientKey: string
protected secureApiConnection = true
protected defaultNamespace: string
protected proxyPort: number
protected kubernetesApi: string
protected prometheusPath: string
protected clusterName: string
constructor(kc: KubeConfig, cluster: Cluster) {
this.id = cluster.id
this.kc = new KubeConfig()
this.kc.users = [
{
name: kc.getCurrentUser().name,
token: this.id
}
]
this.kc.contexts = [
{
name: kc.currentContext,
cluster: kc.getCurrentCluster().name,
user: kc.getCurrentUser().name,
namespace: kc.getContextObject(kc.currentContext).namespace
}
]
this.kc.setCurrentContext(kc.currentContext)
this.cluster = cluster
this.clusterUrl = url.parse(kc.getCurrentCluster().server)
this.contextName = kc.currentContext;
this.defaultNamespace = kc.getContextObject(kc.currentContext).namespace
this.url = `http://${this.id}.localhost:${cluster.port}/`
this.kubernetesApi = `http://127.0.0.1:${cluster.port}/${this.id}`
this.setClusterPreferences(cluster.preferences)
this.kc.clusters = [
{
name: kc.getCurrentCluster().name,
server: this.kubernetesApi,
skipTLSVerify: true
}
]
}
public setClusterPreferences(clusterPreferences?: ClusterPreferences) {
if (clusterPreferences && clusterPreferences.prometheus) {
const prom = clusterPreferences.prometheus
this.prometheusPath = `${prom.namespace}/services/${prom.service}:${prom.port}`
} else {
this.prometheusPath = "lens-metrics/services/prometheus:80"
}
if(clusterPreferences && clusterPreferences.clusterName) {
this.clusterName = clusterPreferences.clusterName;
} else {
this.clusterName = this.contextName;
}
}
public getPrometheusPath() {
return this.prometheusPath
}
public async init() {
const currentCluster = this.kc.getCurrentCluster()
if (currentCluster.caFile) {
this.certData = readFileSync(currentCluster.caFile).toString()
} else if (currentCluster.caData) {
this.certData = Buffer.from(currentCluster.caData, "base64").toString("ascii")
}
const user = this.kc.getCurrentUser()
if (user.authProvider && user.authProvider.name === "oidc") {
const authConfig = user.authProvider.config
if (authConfig["idp-certificate-authority"]) {
this.authCertData = readFileSync(authConfig["idp-certificate-authority"]).toString()
} else if (authConfig["idp-certificate-authority-data"]) {
this.authCertData = Buffer.from(authConfig["idp-certificate-authority-data"], "base64").toString("ascii")
}
}
}
public async getApiTarget() {
if (this.apiTarget) { return this.apiTarget }
this.apiTarget = {
changeOrigin: true,
timeout: 30000,
headers: {
"Host": this.clusterUrl.hostname
},
target: {
port: await this.resolveProxyPort(),
protocol: "http://",
host: "localhost",
path: this.clusterUrl.path
},
}
return this.apiTarget
}
protected async resolveProxyPort(): Promise<number> {
if (this.proxyPort) return this.proxyPort
let serverPort: number = null
try {
serverPort = await getFreePort(49901, 65535)
} catch(error) {
logger.error(error)
throw(error)
}
this.proxyPort = serverPort
return serverPort
}
public applyHeaders(req: http.IncomingMessage) {
req.headers["authorization"] = `Bearer ${this.id}`
}
public async withTemporaryKubeconfig(callback: (kubeconfig: string) => Promise<any>) {
try {
await callback(this.cluster.kubeconfigPath())
} catch(error) {
throw(error)
}
}
public async ensureServer() {
if (!this.proxyServer) {
const proxyPort = await this.resolveProxyPort()
const proxyEnv = Object.assign({}, process.env)
if (this.cluster.preferences && this.cluster.preferences.httpsProxy) {
proxyEnv.HTTPS_PROXY = this.cluster.preferences.httpsProxy
}
this.proxyServer = new KubeAuthProxy(this.cluster, proxyPort, proxyEnv)
await this.proxyServer.run()
}
}
public stopServer() {
if (this.proxyServer) {
this.proxyServer.exit()
this.proxyServer = null
}
}
public proxyServerError() {
if (!this.proxyServer) { return null }
return this.proxyServer.lastError
}
}