mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
154 lines
4.2 KiB
TypeScript
154 lines
4.2 KiB
TypeScript
import * as k8s from "@kubernetes/client-node"
|
||
import * as os from "os"
|
||
import * as yaml from "js-yaml"
|
||
import logger from "./logger";
|
||
|
||
const kc = new k8s.KubeConfig()
|
||
|
||
function resolveTilde(filePath: string) {
|
||
if (filePath[0] === "~" && (filePath[1] === "/" || filePath.length === 1)) {
|
||
return filePath.replace("~", os.homedir());
|
||
}
|
||
return filePath;
|
||
}
|
||
|
||
export function loadConfig(kubeconfig: string): k8s.KubeConfig {
|
||
if (kubeconfig) {
|
||
kc.loadFromFile(resolveTilde(kubeconfig))
|
||
} else {
|
||
kc.loadFromDefault();
|
||
}
|
||
return kc
|
||
}
|
||
|
||
/**
|
||
* KubeConfig is valid when there's atleast one of each defined:
|
||
* - User
|
||
* - Cluster
|
||
* - Context
|
||
*
|
||
* @param config KubeConfig to check
|
||
*/
|
||
export function valideConfig(config: k8s.KubeConfig): boolean {
|
||
logger.debug(`validating kube config: ${JSON.stringify(config)}`)
|
||
if(!config.users || config.users.length == 0) {
|
||
throw new Error("No users provided in config")
|
||
}
|
||
|
||
if(!config.clusters || config.clusters.length == 0) {
|
||
throw new Error("No clusters provided in config")
|
||
}
|
||
|
||
if(!config.contexts || config.contexts.length == 0) {
|
||
throw new Error("No contexts provided in config")
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
|
||
/**
|
||
* Breaks kube config into several configs. Each context as it own KubeConfig object
|
||
*
|
||
* @param configString yaml string of kube config
|
||
*/
|
||
export function splitConfig(kubeConfig: k8s.KubeConfig): k8s.KubeConfig[] {
|
||
const configs: k8s.KubeConfig[] = []
|
||
if(!kubeConfig.contexts) {
|
||
return configs;
|
||
}
|
||
kubeConfig.contexts.forEach(ctx => {
|
||
const kc = new k8s.KubeConfig();
|
||
kc.clusters = [kubeConfig.getCluster(ctx.cluster)].filter(n => n);
|
||
kc.users = [kubeConfig.getUser(ctx.user)].filter(n => n)
|
||
kc.contexts = [kubeConfig.getContextObject(ctx.name)].filter(n => n)
|
||
kc.setCurrentContext(ctx.name);
|
||
|
||
configs.push(kc);
|
||
});
|
||
return configs;
|
||
}
|
||
|
||
/**
|
||
* Loads KubeConfig from a yaml string and breaks it into several configs. Each context
|
||
*
|
||
* @param configString yaml string of kube config
|
||
*/
|
||
export function loadAndSplitConfig(configString: string): k8s.KubeConfig[] {
|
||
const allConfigs = new k8s.KubeConfig();
|
||
allConfigs.loadFromString(configString);
|
||
return splitConfig(allConfigs);
|
||
}
|
||
|
||
export function dumpConfigYaml(kc: k8s.KubeConfig): string {
|
||
const config = {
|
||
apiVersion: "v1",
|
||
kind: "Config",
|
||
preferences: {},
|
||
'current-context': kc.currentContext,
|
||
clusters: kc.clusters.map(c => {
|
||
return {
|
||
name: c.name,
|
||
cluster: {
|
||
'certificate-authority-data': c.caData,
|
||
'certificate-authority': c.caFile,
|
||
server: c.server,
|
||
'insecure-skip-tls-verify': c.skipTLSVerify
|
||
}
|
||
}
|
||
}),
|
||
contexts: kc.contexts.map(c => {
|
||
return {
|
||
name: c.name,
|
||
context: {
|
||
cluster: c.cluster,
|
||
user: c.user,
|
||
namespace: c.namespace
|
||
}
|
||
}
|
||
}),
|
||
users: kc.users.map(u => {
|
||
return {
|
||
name: u.name,
|
||
user: {
|
||
'client-certificate-data': u.certData,
|
||
'client-certificate': u.certFile,
|
||
'client-key-data': u.keyData,
|
||
'client-key': u.keyFile,
|
||
'auth-provider': u.authProvider,
|
||
exec: u.exec,
|
||
token: u.token,
|
||
username: u.username,
|
||
password: u.password
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
console.log("dumping kc:", config);
|
||
|
||
// skipInvalid: true makes dump ignore undefined values
|
||
return yaml.safeDump(config, {skipInvalid: true});
|
||
}
|
||
|
||
export function podHasIssues(pod: k8s.V1Pod) {
|
||
// Logic adapted from dashboard
|
||
const notReady = !!pod.status.conditions.find(condition => {
|
||
return condition.type == "Ready" && condition.status !== "True"
|
||
});
|
||
|
||
return (
|
||
notReady ||
|
||
pod.status.phase !== "Running" ||
|
||
pod.spec.priority > 500000 // We're interested in high prio pods events regardless of their running status
|
||
)
|
||
}
|
||
|
||
// Logic adapted from dashboard
|
||
// see: https://github.com/kontena/kontena-k8s-dashboard/blob/7d8f9cb678cc817a22dd1886c5e79415b212b9bf/client/api/endpoints/nodes.api.ts#L147
|
||
export function getNodeWarningConditions(node: k8s.V1Node) {
|
||
return node.status.conditions.filter(c =>
|
||
c.status.toLowerCase() === "true" && c.type !== "Ready" && c.type !== "HostUpgrades"
|
||
)
|
||
}
|