mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add support for specifying NO_PROXY on a per cluster level
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
4b1d740d61
commit
b491a5c875
35
packages/core/src/common/cluster-env.injectable.ts
Normal file
35
packages/core/src/common/cluster-env.injectable.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import type { Cluster } from "./cluster/cluster";
|
||||
import { object } from "./utils";
|
||||
|
||||
function isDefinedEntry<T>(entry: readonly [T, string | undefined]): entry is [T, string] {
|
||||
return Boolean(entry[1]);
|
||||
}
|
||||
|
||||
export interface ClusterEnvironment {
|
||||
HTTPS_PROXY?: string;
|
||||
NO_PROXY?: string;
|
||||
}
|
||||
|
||||
const clusterEnvironmentInjectable = getInjectable({
|
||||
id: "cluster-environment",
|
||||
instantiate: (di, cluster) => computed(() => {
|
||||
const { preferences } = cluster;
|
||||
const entries = [
|
||||
["HTTPS_PROXY", preferences.httpsProxy],
|
||||
["NO_PROXY", preferences.noProxy],
|
||||
] as const;
|
||||
|
||||
return object.fromEntries(entries.filter(isDefinedEntry)) as ClusterEnvironment;
|
||||
}),
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, cluster: Cluster) => cluster.id,
|
||||
}),
|
||||
});
|
||||
|
||||
export default clusterEnvironmentInjectable;
|
||||
@ -106,6 +106,7 @@ export interface ClusterPreferences extends ClusterPrometheusPreferences {
|
||||
*/
|
||||
icon?: string | null;
|
||||
httpsProxy?: string;
|
||||
noProxy?: string;
|
||||
hiddenMetrics?: string[];
|
||||
nodeShellImage?: string;
|
||||
imagePullSecret?: string;
|
||||
|
||||
@ -9,6 +9,7 @@ import type { Cluster } from "../../common/cluster/cluster";
|
||||
import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
|
||||
import kubeAuthProxyCertificateInjectable from "../kube-auth-proxy/kube-auth-proxy-certificate.injectable";
|
||||
import type { KubeAuthProxy } from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
|
||||
import clusterEnvironmentInjectable from "../../common/cluster-env.injectable";
|
||||
|
||||
export interface KubeAuthProxyServer {
|
||||
getApiTarget(isLongRunningRequest?: boolean): Promise<ServerOptions>;
|
||||
@ -26,6 +27,7 @@ const kubeAuthProxyServerInjectable = getInjectable({
|
||||
instantiate: (di, cluster): KubeAuthProxyServer => {
|
||||
const clusterUrl = new URL(cluster.apiUrl.get());
|
||||
|
||||
const clusterEnvironment = di.inject(clusterEnvironmentInjectable, cluster);
|
||||
const createKubeAuthProxy = di.inject(createKubeAuthProxyInjectable);
|
||||
const certificate = di.inject(kubeAuthProxyCertificateInjectable, clusterUrl.hostname);
|
||||
|
||||
@ -34,7 +36,10 @@ const kubeAuthProxyServerInjectable = getInjectable({
|
||||
|
||||
const ensureServerHelper = async (): Promise<KubeAuthProxy> => {
|
||||
if (!kubeAuthProxy) {
|
||||
const proxyEnv = Object.assign({}, process.env);
|
||||
const proxyEnv = {
|
||||
...process.env,
|
||||
...clusterEnvironment.get(),
|
||||
};
|
||||
|
||||
if (cluster.preferences.httpsProxy) {
|
||||
proxyEnv.HTTPS_PROXY = cluster.preferences.httpsProxy;
|
||||
|
||||
@ -17,6 +17,8 @@ import type { JoinPaths } from "../../common/path/join-paths.injectable";
|
||||
import type { CreateKubectl } from "../kubectl/create-kubectl.injectable";
|
||||
import type { KubeconfigManager } from "../kubeconfig-manager/kubeconfig-manager";
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import type { ClusterEnvironment } from "../../common/cluster-env.injectable";
|
||||
|
||||
export interface ResourceApplierDependencies {
|
||||
emitAppEvent: EmitAppEvent;
|
||||
@ -27,6 +29,7 @@ export interface ResourceApplierDependencies {
|
||||
createKubectl: CreateKubectl;
|
||||
readonly proxyKubeconfigManager: KubeconfigManager;
|
||||
readonly logger: Logger;
|
||||
readonly clusterEnvironment: IComputedValue<ClusterEnvironment>;
|
||||
}
|
||||
|
||||
export class ResourceApplier {
|
||||
@ -100,17 +103,17 @@ export class ResourceApplier {
|
||||
|
||||
this.dependencies.logger.debug(`shooting manifests with ${kubectlPath}`, { args });
|
||||
|
||||
const execEnv = { ...process.env };
|
||||
const httpsProxy = this.cluster.preferences?.httpsProxy;
|
||||
|
||||
if (httpsProxy) {
|
||||
execEnv.HTTPS_PROXY = httpsProxy;
|
||||
}
|
||||
const execEnv = {
|
||||
...process.env,
|
||||
...this.dependencies.clusterEnvironment.get(),
|
||||
};
|
||||
|
||||
try {
|
||||
await this.dependencies.writeFile(fileName, content);
|
||||
|
||||
const result = await this.dependencies.execFile(kubectlPath, args);
|
||||
const result = await this.dependencies.execFile(kubectlPath, args, {
|
||||
env: execEnv,
|
||||
});
|
||||
|
||||
if (result.callWasSuccessful) {
|
||||
return result;
|
||||
|
||||
@ -19,6 +19,7 @@ import type { InitializableState } from "../../common/initializable-state/create
|
||||
import type { EmitAppEvent } from "../../common/app-event-bus/emit-event.injectable";
|
||||
import type { Stat } from "../../common/fs/stat.injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import type { ClusterEnvironment } from "../../common/cluster-env.injectable";
|
||||
|
||||
export class ShellOpenError extends Error {
|
||||
constructor(message: string, options?: ErrorOptions) {
|
||||
@ -113,6 +114,7 @@ export interface ShellSessionDependencies {
|
||||
readonly buildVersion: InitializableState<string>;
|
||||
readonly proxyKubeconfigPath: string;
|
||||
readonly directoryContainingKubectl: string;
|
||||
readonly clusterEnvironment: IComputedValue<ClusterEnvironment>;
|
||||
computeShellEnvironment: ComputeShellEnvironment;
|
||||
spawnPty: SpawnPty;
|
||||
emitAppEvent: EmitAppEvent;
|
||||
@ -347,7 +349,10 @@ export abstract class ShellSession {
|
||||
return process.env;
|
||||
})();
|
||||
|
||||
const env = clearKubeconfigEnvVars(JSON.parse(JSON.stringify(rawEnv)));
|
||||
const env: Partial<Record<string, string>> = {
|
||||
...clearKubeconfigEnvVars(JSON.parse(JSON.stringify(rawEnv))),
|
||||
...this.dependencies.clusterEnvironment.get(),
|
||||
};
|
||||
const pathStr = [this.dependencies.directoryContainingKubectl, ...this.getPathEntries(), env.PATH].join(path.delimiter);
|
||||
|
||||
delete env.DEBUG; // don't pass DEBUG into shells
|
||||
@ -380,10 +385,6 @@ export abstract class ShellSession {
|
||||
env.TERM_PROGRAM = this.dependencies.appName;
|
||||
env.TERM_PROGRAM_VERSION = this.dependencies.buildVersion.get();
|
||||
|
||||
if (this.cluster.preferences.httpsProxy) {
|
||||
env.HTTPS_PROXY = this.cluster.preferences.httpsProxy;
|
||||
}
|
||||
|
||||
env.NO_PROXY = [
|
||||
"localhost",
|
||||
"127.0.0.1",
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { observable, autorun, makeObservable } from "mobx";
|
||||
import { observer, disposeOnUnmount } from "mobx-react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { action } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import type { Cluster } from "../../../common/cluster/cluster";
|
||||
import { Input, InputValidators } from "../input";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
@ -14,47 +14,47 @@ export interface ClusterProxySettingProps {
|
||||
cluster: Cluster;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class ClusterProxySetting extends React.Component<ClusterProxySettingProps> {
|
||||
@observable proxy = "";
|
||||
export const ClusterProxySetting = observer((props: ClusterProxySettingProps) => {
|
||||
const { cluster } = props;
|
||||
|
||||
constructor(props: ClusterProxySettingProps) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
const [httpsProxy, setHttpsProxy] = useState(cluster.preferences.httpsProxy || "");
|
||||
const [noProxy, setNoProxy] = useState(cluster.preferences.noProxy || "");
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this,
|
||||
autorun(() => {
|
||||
this.proxy = this.props.cluster.preferences.httpsProxy || "";
|
||||
}),
|
||||
);
|
||||
}
|
||||
useEffect(() => action(() => {
|
||||
cluster.preferences.httpsProxy = httpsProxy;
|
||||
cluster.preferences.noProxy = noProxy;
|
||||
}), []);
|
||||
|
||||
save = () => {
|
||||
this.props.cluster.preferences.httpsProxy = this.proxy;
|
||||
};
|
||||
|
||||
onChange = (value: string) => {
|
||||
this.proxy = value;
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<SubTitle title="HTTP Proxy" id="http-proxy" />
|
||||
<Input
|
||||
theme="round-black"
|
||||
value={this.proxy}
|
||||
onChange={this.onChange}
|
||||
onBlur={this.save}
|
||||
placeholder="http://<address>:<port>"
|
||||
validators={this.proxy ? InputValidators.isUrl : undefined}
|
||||
/>
|
||||
<small className="hint">
|
||||
HTTP Proxy server. Used for communicating with Kubernetes API.
|
||||
</small>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<SubTitle title="HTTPS Proxy" id="http-proxy" />
|
||||
<Input
|
||||
theme="round-black"
|
||||
value={httpsProxy}
|
||||
onChange={setHttpsProxy}
|
||||
onBlur={() => {
|
||||
props.cluster.preferences.httpsProxy = httpsProxy;
|
||||
}}
|
||||
placeholder="https://<address>:<port>"
|
||||
validators={httpsProxy ? InputValidators.isUrl : undefined}
|
||||
/>
|
||||
<small className="hint">
|
||||
HTTPS Proxy server. Used for communicating with Kubernetes API.
|
||||
</small>
|
||||
<SubTitle title="No Proxy" id="no-proxy" />
|
||||
<Input
|
||||
theme="round-black"
|
||||
value={noProxy}
|
||||
onChange={setNoProxy}
|
||||
onBlur={() => {
|
||||
props.cluster.preferences.noProxy = noProxy;
|
||||
}}
|
||||
placeholder=""
|
||||
validators={noProxy ? InputValidators.isUrl : undefined}
|
||||
/>
|
||||
<small className="hint">
|
||||
NO_PROXY configuration. Useful for when specifying that cluster communication shouldn't go through the default proxy.
|
||||
</small>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user