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

Fix check for user exec command (#3664)

This commit is contained in:
Sebastian Malton 2021-09-15 13:09:57 -04:00 committed by GitHub
parent 068c78d48d
commit 056b818ceb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 62 additions and 23 deletions

View File

@ -185,6 +185,7 @@
"@kubernetes/client-node": "^0.15.1", "@kubernetes/client-node": "^0.15.1",
"@sentry/electron": "^2.5.0", "@sentry/electron": "^2.5.0",
"@sentry/integrations": "^6.10.0", "@sentry/integrations": "^6.10.0",
"@types/which": "^2.0.1",
"abort-controller": "^3.0.0", "abort-controller": "^3.0.0",
"array-move": "^3.0.1", "array-move": "^3.0.1",
"auto-bind": "^4.0.0", "auto-bind": "^4.0.0",
@ -193,7 +194,6 @@
"byline": "^5.0.0", "byline": "^5.0.0",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"chokidar": "^3.4.3", "chokidar": "^3.4.3",
"command-exists": "1.2.9",
"conf": "^7.0.1", "conf": "^7.0.1",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"electron-devtools-installer": "^3.2.0", "electron-devtools-installer": "^3.2.0",
@ -246,6 +246,7 @@
"tempy": "^0.5.0", "tempy": "^0.5.0",
"url-parse": "^1.5.1", "url-parse": "^1.5.1",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"which": "^2.0.2",
"win-ca": "^3.2.0", "win-ca": "^3.2.0",
"winston": "^3.3.3", "winston": "^3.3.3",
"winston-console-format": "^1.0.8", "winston-console-format": "^1.0.8",

View File

@ -19,15 +19,18 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
import path from "path";
export class ExecValidationNotFoundError extends Error { export class ExecValidationNotFoundError extends Error {
constructor(execPath: string, isAbsolute: boolean) { constructor(execPath: string) {
super(`User Exec command "${execPath}" not found on host.`);
let message = `User Exec command "${execPath}" not found on host.`; let message = `User Exec command "${execPath}" not found on host.`;
if (!isAbsolute) { if (!path.isAbsolute(execPath)) {
message += ` Please ensure binary is found in PATH or use absolute path to binary in Kubeconfig`; message += ` Please ensure binary is found in PATH or use absolute path to binary in Kubeconfig`;
} }
this.message = message;
super(message);
this.name = this.constructor.name; this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor); Error.captureStackTrace(this, this.constructor);
} }

View File

@ -25,11 +25,11 @@ import path from "path";
import os from "os"; import os from "os";
import yaml from "js-yaml"; import yaml from "js-yaml";
import logger from "../main/logger"; import logger from "../main/logger";
import commandExists from "command-exists";
import { ExecValidationNotFoundError } from "./custom-errors"; import { ExecValidationNotFoundError } from "./custom-errors";
import { Cluster, Context, newClusters, newContexts, newUsers, User } from "@kubernetes/client-node/dist/config_types"; import { Cluster, Context, newClusters, newContexts, newUsers, User } from "@kubernetes/client-node/dist/config_types";
import { resolvePath } from "./utils"; import { resolvePath } from "./utils";
import Joi from "joi"; import Joi from "joi";
import which from "which";
export type KubeConfigValidationOpts = { export type KubeConfigValidationOpts = {
validateCluster?: boolean; validateCluster?: boolean;
@ -295,13 +295,17 @@ export function validateKubeConfig(config: KubeConfig, contextName: string, vali
// Validate exec command if present // Validate exec command if present
if (validateExec && user?.exec) { if (validateExec && user?.exec) {
const execCommand = user.exec["command"]; try {
// check if the command is absolute or not which.sync(user.exec.command);
const isAbsolute = path.isAbsolute(execCommand);
// validate the exec struct in the user object, start with the command field // If this doesn't throw an error it also means that it has found the executable.
if (!commandExists.sync(execCommand)) { } catch (error) {
return new ExecValidationNotFoundError(execCommand, isAbsolute); switch (error?.code) {
case "ENOENT":
return new ExecValidationNotFoundError(user.exec.command);
default:
return error;
}
} }
} }

View File

@ -50,4 +50,11 @@
display: block; display: block;
padding-top: 6px; padding-top: 6px;
} }
.actions-panel {
.Spinner {
vertical-align: middle;
margin-left: $spacing;
}
}
} }

View File

@ -24,7 +24,7 @@ import "./add-cluster.scss";
import type { KubeConfig } from "@kubernetes/client-node"; import type { KubeConfig } from "@kubernetes/client-node";
import fse from "fs-extra"; import fse from "fs-extra";
import { debounce } from "lodash"; import { debounce } from "lodash";
import { action, computed, observable, makeObservable } from "mobx"; import { action, computed, observable, makeObservable, runInAction } from "mobx";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import path from "path"; import path from "path";
import React from "react"; import React from "react";
@ -41,6 +41,7 @@ import { SettingLayout } from "../layout/setting-layout";
import MonacoEditor from "react-monaco-editor"; import MonacoEditor from "react-monaco-editor";
import { ThemeStore } from "../../theme.store"; import { ThemeStore } from "../../theme.store";
import { UserStore } from "../../../common/user-store"; import { UserStore } from "../../../common/user-store";
import { Spinner } from "../spinner";
interface Option { interface Option {
config: KubeConfig; config: KubeConfig;
@ -62,6 +63,7 @@ export class AddCluster extends React.Component {
@observable kubeContexts = observable.map<string, Option>(); @observable kubeContexts = observable.map<string, Option>();
@observable customConfig = ""; @observable customConfig = "";
@observable isWaiting = false; @observable isWaiting = false;
@observable isCheckingInput = false;
@observable errorText: string; @observable errorText: string;
constructor(props: {}) { constructor(props: {}) {
@ -80,14 +82,35 @@ export class AddCluster extends React.Component {
].filter(Boolean); ].filter(Boolean);
} }
@action _refreshContexts = debounce(() => {
refreshContexts = debounce(() => { runInAction(() => {
const { config, error } = loadConfigFromString(this.customConfig.trim() || "{}"); try {
const text = this.customConfig.trim();
this.kubeContexts.replace(getContexts(config)); if (!text) {
this.errorText = error?.toString(); return this.kubeContexts.clear();
}
const { config, error } = loadConfigFromString(text);
this.kubeContexts.replace(getContexts(config));
this.errorText = error?.toString();
} catch (error) {
this.kubeContexts.clear();
this.errorText = error?.toString() || "An error occured";
} finally {
this.isCheckingInput = false;
}
});
}, 500); }, 500);
refreshContexts = () => {
// Clear the kubeContexts immediately
this.isCheckingInput = true;
this.kubeContexts.clear();
this._refreshContexts();
};
@action @action
addClusters = async () => { addClusters = async () => {
this.isWaiting = true; this.isWaiting = true;
@ -145,6 +168,7 @@ export class AddCluster extends React.Component {
tooltip={this.kubeContexts.size === 0 || "Paste in at least one cluster to add."} tooltip={this.kubeContexts.size === 0 || "Paste in at least one cluster to add."}
tooltipOverrideDisabled tooltipOverrideDisabled
/> />
{this.isCheckingInput && <Spinner />}
</div> </div>
</SettingLayout> </SettingLayout>
); );

View File

@ -2184,6 +2184,11 @@
anymatch "^3.0.0" anymatch "^3.0.0"
source-map "^0.6.0" source-map "^0.6.0"
"@types/which@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/which/-/which-2.0.1.tgz#27ecd67f915b7c3d6ba552135bb1eecd66e63501"
integrity sha512-Jjakcv8Roqtio6w1gr0D7y6twbhx6gGgFGF5BLwajPpnOIOxFkakFhCq+LmyyeAz7BX6ULrjBOxdKaCDy+4+dQ==
"@types/ws@^6.0.1": "@types/ws@^6.0.1":
version "6.0.4" version "6.0.4"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-6.0.4.tgz#7797707c8acce8f76d8c34b370d4645b70421ff1" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-6.0.4.tgz#7797707c8acce8f76d8c34b370d4645b70421ff1"
@ -4110,11 +4115,6 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
dependencies: dependencies:
delayed-stream "~1.0.0" delayed-stream "~1.0.0"
command-exists@1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69"
integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==
commander@2.9.0: commander@2.9.0:
version "2.9.0" version "2.9.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"