1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Support window nodes for node-shells (#3624)

* Support window nodes for node-shells

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Also check beta.kubernetes/os label

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add comment about linux fallback

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-11-08 20:11:40 -05:00 committed by GitHub
parent c09a57370e
commit 5eb1b8553d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 24 deletions

View File

@ -236,13 +236,10 @@ export class Node extends KubeObject {
} }
getOperatingSystem(): string { getOperatingSystem(): string {
const label = this.getLabels().find(label => label.startsWith("kubernetes.io/os=")); return this.metadata?.labels?.["kubernetes.io/os"]
|| this.metadata?.labels?.["beta.kubernetes.io/os"]
if (label) { || this.status?.nodeInfo?.operatingSystem
return label.split("=", 2)[1]; || "linux";
}
return "linux";
} }
isUnschedulable() { isUnschedulable() {

View File

@ -224,10 +224,7 @@ export class KubeApi<T extends KubeObject> {
isNamespaced = options.objectConstructor?.namespaced, isNamespaced = options.objectConstructor?.namespaced,
} = options || {}; } = options || {};
if (!options.apiBase) { const { apiBase, apiPrefix, apiGroup, apiVersion, resource } = parseKubeApi(options.apiBase || objectConstructor.apiBase);
options.apiBase = objectConstructor.apiBase;
}
const { apiBase, apiPrefix, apiGroup, apiVersion, resource } = parseKubeApi(options.apiBase);
this.kind = kind; this.kind = kind;
this.isNamespaced = isNamespaced; this.isNamespaced = isNamespaced;

View File

@ -21,6 +21,9 @@
import { JsonApi, JsonApiData, JsonApiError } from "./json-api"; import { JsonApi, JsonApiData, JsonApiError } from "./json-api";
import type { Response } from "node-fetch"; import type { Response } from "node-fetch";
import type { Cluster } from "../../main/cluster";
import { LensProxy } from "../../main/lens-proxy";
import { apiKubePrefix, isDebugging } from "../vars";
export interface KubeJsonApiListMetadata { export interface KubeJsonApiListMetadata {
resourceVersion: string; resourceVersion: string;
@ -70,6 +73,20 @@ export interface KubeJsonApiError extends JsonApiError {
} }
export class KubeJsonApi extends JsonApi<KubeJsonApiData> { export class KubeJsonApi extends JsonApi<KubeJsonApiData> {
static forCluster(cluster: Cluster): KubeJsonApi {
const port = LensProxy.getInstance().port;
return new this({
serverAddress: `http://127.0.0.1:${port}`,
apiBase: apiKubePrefix,
debug: isDebugging,
}, {
headers: {
"Host": `${cluster.id}.localhost:${port}`,
},
});
}
protected parseError(error: KubeJsonApiError | any, res: Response): string[] { protected parseError(error: KubeJsonApiError | any, res: Response): string[] {
const { status, reason, message } = error; const { status, reason, message } = error;
@ -80,4 +97,3 @@ export class KubeJsonApi extends JsonApi<KubeJsonApiData> {
return super.parseError(error, res); return super.parseError(error, res);
} }
} }

View File

@ -240,28 +240,21 @@ export class ClusterManager extends Singleton {
} }
getClusterForRequest(req: http.IncomingMessage): Cluster { getClusterForRequest(req: http.IncomingMessage): Cluster {
let cluster: Cluster = null;
// lens-server is connecting to 127.0.0.1:<port>/<uid> // lens-server is connecting to 127.0.0.1:<port>/<uid>
if (req.headers.host.startsWith("127.0.0.1")) { if (req.headers.host.startsWith("127.0.0.1")) {
const clusterId = req.url.split("/")[1]; const clusterId = req.url.split("/")[1];
const cluster = this.store.getById(clusterId);
cluster = this.store.getById(clusterId);
if (cluster) { if (cluster) {
// we need to swap path prefix so that request is proxied to kube api // we need to swap path prefix so that request is proxied to kube api
req.url = req.url.replace(`/${clusterId}`, apiKubePrefix); req.url = req.url.replace(`/${clusterId}`, apiKubePrefix);
} }
} else if (req.headers["x-cluster-id"]) {
cluster = this.store.getById(req.headers["x-cluster-id"].toString());
} else {
const clusterId = getClusterIdFromHost(req.headers.host);
cluster = this.store.getById(clusterId);
}
return cluster; return cluster;
} }
return this.store.getById(getClusterIdFromHost(req.headers.host));
}
} }
export function catalogEntityFromCluster(cluster: Cluster) { export function catalogEntityFromCluster(cluster: Cluster) {

View File

@ -26,6 +26,9 @@ import type { KubeConfig } from "@kubernetes/client-node";
import type { Cluster } from "../cluster"; import type { Cluster } from "../cluster";
import { ShellOpenError, ShellSession } from "./shell-session"; import { ShellOpenError, ShellSession } from "./shell-session";
import { get } from "lodash"; import { get } from "lodash";
import { Node, NodesApi } from "../../common/k8s-api/endpoints";
import { KubeJsonApi } from "../../common/k8s-api/kube-json-api";
import logger from "../logger";
export class NodeShellSession extends ShellSession { export class NodeShellSession extends ShellSession {
ShellType = "node-shell"; ShellType = "node-shell";
@ -55,10 +58,27 @@ export class NodeShellSession extends ShellSession {
throw new ShellOpenError("failed to create node pod", error); throw new ShellOpenError("failed to create node pod", error);
} }
const args = ["exec", "-i", "-t", "-n", "kube-system", this.podId, "--", "sh", "-c", "((clear && bash) || (clear && ash) || (clear && sh))"];
const env = await this.getCachedShellEnv(); const env = await this.getCachedShellEnv();
const args = ["exec", "-i", "-t", "-n", "kube-system", this.podId, "--"];
const nodeApi = new NodesApi({
objectConstructor: Node,
request: KubeJsonApi.forCluster(this.cluster),
});
const node = await nodeApi.get({ name: this.nodeName });
const nodeOs = node.getOperatingSystem();
await super.open(shell, args, env); switch (nodeOs) {
default:
logger.warn(`[NODE-SHELL-SESSION]: could not determine node OS, falling back with assumption of linux`);
case "linux":
args.push("sh", "-c", "((clear && bash) || (clear && ash) || (clear && sh))");
break;
case "windows":
args.push("powershell");
break;
}
return super.open(shell, args, env);
} }
protected createNodeShellPod() { protected createNodeShellPod() {