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:
1 parent
068c78d48d
commit
056b818ceb
6 files changed
+62
-23
No files matched your search
@@ -19,15 +19,18 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import path from "path";
|
||||
|
||||
export class ExecValidationNotFoundError extends Error {
|
||||
constructor(execPath: string, isAbsolute: boolean) {
|
||||
super(`User Exec command "${execPath}" not found on host.`);
|
||||
constructor(execPath: string) {
|
||||
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`;
|
||||
}
|
||||
this.message = message;
|
||||
|
||||
super(message);
|
||||
|
||||
this.name = this.constructor.name;
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ import path from "path";
|
||||
import os from "os";
|
||||
import yaml from "js-yaml";
|
||||
import logger from "../main/logger";
|
||||
import commandExists from "command-exists";
|
||||
import { ExecValidationNotFoundError } from "./custom-errors";
|
||||
import { Cluster, Context, newClusters, newContexts, newUsers, User } from "@kubernetes/client-node/dist/config_types";
|
||||
import { resolvePath } from "./utils";
|
||||
import Joi from "joi";
|
||||
import which from "which";
|
||||
|
||||
export type KubeConfigValidationOpts = {
|
||||
validateCluster?: boolean;
|
||||
@@ -295,13 +295,17 @@ export function validateKubeConfig(config: KubeConfig, contextName: string, vali
|
||||
|
||||
// Validate exec command if present
|
||||
if (validateExec && user?.exec) {
|
||||
const execCommand = user.exec["command"];
|
||||
// check if the command is absolute or not
|
||||
const isAbsolute = path.isAbsolute(execCommand);
|
||||
try {
|
||||
which.sync(user.exec.command);
|
||||
|
||||
// validate the exec struct in the user object, start with the command field
|
||||
if (!commandExists.sync(execCommand)) {
|
||||
return new ExecValidationNotFoundError(execCommand, isAbsolute);
|
||||
// If this doesn't throw an error it also means that it has found the executable.
|
||||
} catch (error) {
|
||||
switch (error?.code) {
|
||||
case "ENOENT":
|
||||
return new ExecValidationNotFoundError(user.exec.command);
|
||||
default:
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,4 +50,11 @@
|
||||
display: block;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.actions-panel {
|
||||
.Spinner {
|
||||
vertical-align: middle;
|
||||
margin-left: $spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import "./add-cluster.scss";
|
||||
import type { KubeConfig } from "@kubernetes/client-node";
|
||||
import fse from "fs-extra";
|
||||
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 path from "path";
|
||||
import React from "react";
|
||||
@@ -41,6 +41,7 @@ import { SettingLayout } from "../layout/setting-layout";
|
||||
import MonacoEditor from "react-monaco-editor";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { UserStore } from "../../../common/user-store";
|
||||
import { Spinner } from "../spinner";
|
||||
|
||||
interface Option {
|
||||
config: KubeConfig;
|
||||
@@ -62,6 +63,7 @@ export class AddCluster extends React.Component {
|
||||
@observable kubeContexts = observable.map<string, Option>();
|
||||
@observable customConfig = "";
|
||||
@observable isWaiting = false;
|
||||
@observable isCheckingInput = false;
|
||||
@observable errorText: string;
|
||||
|
||||
constructor(props: {}) {
|
||||
@@ -80,14 +82,35 @@ export class AddCluster extends React.Component {
|
||||
].filter(Boolean);
|
||||
}
|
||||
|
||||
@action
|
||||
refreshContexts = debounce(() => {
|
||||
const { config, error } = loadConfigFromString(this.customConfig.trim() || "{}");
|
||||
_refreshContexts = debounce(() => {
|
||||
runInAction(() => {
|
||||
try {
|
||||
const text = this.customConfig.trim();
|
||||
|
||||
this.kubeContexts.replace(getContexts(config));
|
||||
this.errorText = error?.toString();
|
||||
if (!text) {
|
||||
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);
|
||||
|
||||
refreshContexts = () => {
|
||||
// Clear the kubeContexts immediately
|
||||
this.isCheckingInput = true;
|
||||
this.kubeContexts.clear();
|
||||
this._refreshContexts();
|
||||
};
|
||||
|
||||
@action
|
||||
addClusters = async () => {
|
||||
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."}
|
||||
tooltipOverrideDisabled
|
||||
/>
|
||||
{this.isCheckingInput && <Spinner />}
|
||||
</div>
|
||||
</SettingLayout>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user