diff --git a/src/common/cluster-store.ts b/src/common/cluster-store.ts index fa5219ceb6..b6e198a213 100644 --- a/src/common/cluster-store.ts +++ b/src/common/cluster-store.ts @@ -101,6 +101,8 @@ export interface ClusterPreferences extends ClusterPrometheusPreferences { icon?: string; httpsProxy?: string; hiddenMetrics?: string[]; + nodeShellImage?: string; + imagePullSecret?: string; } export interface ClusterPrometheusPreferences { @@ -117,6 +119,8 @@ export interface ClusterPrometheusPreferences { const initialStates = "cluster:states"; +export const initialNodeShellImage = "docker.io/alpine:3.13"; + export class ClusterStore extends BaseStore { private static StateChannel = "cluster:state"; diff --git a/src/main/cluster.ts b/src/main/cluster.ts index 1266a9c00a..bf893f8484 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -34,6 +34,7 @@ import { VersionDetector } from "./cluster-detectors/version-detector"; import { detectorRegistry } from "./cluster-detectors/detector-registry"; import plimit from "p-limit"; import { toJS } from "../common/utils"; +import { initialNodeShellImage } from "../common/cluster-store"; export enum ClusterStatus { AccessGranted = 2, @@ -745,4 +746,12 @@ export class Cluster implements ClusterModel, ClusterState { isMetricHidden(resource: ClusterMetricsResourceType): boolean { return Boolean(this.preferences.hiddenMetrics?.includes(resource)); } + + get nodeShellImage(): string { + return this.preferences.nodeShellImage || initialNodeShellImage; + } + + get imagePullSecret(): string { + return this.preferences.imagePullSecret || ""; + } } diff --git a/src/main/shell-session/node-shell-session.ts b/src/main/shell-session/node-shell-session.ts index a3cc918371..7542baecd6 100644 --- a/src/main/shell-session/node-shell-session.ts +++ b/src/main/shell-session/node-shell-session.ts @@ -77,13 +77,16 @@ export class NodeShellSession extends ShellSession { }], containers: [{ name: "shell", - image: "docker.io/alpine:3.13", + image: this.cluster.nodeShellImage, securityContext: { privileged: true, }, command: ["nsenter"], args: ["-t", "1", "-m", "-u", "-i", "-n", "sleep", "14000"] }], + imagePullSecrets: [{ + name: this.cluster.imagePullSecret, + }] } }); } diff --git a/src/renderer/components/cluster-settings/cluster-settings.tsx b/src/renderer/components/cluster-settings/cluster-settings.tsx index 2f11883fa0..21081bc5ce 100644 --- a/src/renderer/components/cluster-settings/cluster-settings.tsx +++ b/src/renderer/components/cluster-settings/cluster-settings.tsx @@ -118,3 +118,17 @@ export function MetricsSettings({ entity }: EntitySettingViewProps) { ); } + +export function NodeShellSettings({entity}: EntitySettingViewProps) { + const cluster = getClusterForEntity(entity); + + if(!cluster) { + return null; + } + + return ( +
+ +
+ ); +} diff --git a/src/renderer/components/cluster-settings/components/cluster-node-shell-setting.tsx b/src/renderer/components/cluster-settings/components/cluster-node-shell-setting.tsx new file mode 100644 index 0000000000..a5b4300fe3 --- /dev/null +++ b/src/renderer/components/cluster-settings/components/cluster-node-shell-setting.tsx @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import type { Cluster } from "../../../../main/cluster"; +import { autorun, makeObservable, observable } from "mobx"; +import { SubTitle } from "../../layout/sub-title"; +import React from "react"; +import { Input } from "../../input/input"; +import { disposeOnUnmount, observer } from "mobx-react"; +import { Icon } from "../../icon/icon"; +import { initialNodeShellImage } from "../../../../common/cluster-store"; + +interface Props { + cluster: Cluster; +} + +@observer +export class ClusterNodeShellSetting extends React.Component { + @observable nodeShellImage = ""; + @observable imagePullSecret = ""; + + constructor(props: Props) { + super(props); + makeObservable(this); + } + + componentDidMount() { + disposeOnUnmount(this, + autorun(() => { + this.nodeShellImage = this.props.cluster.nodeShellImage; + this.imagePullSecret = this.props.cluster.imagePullSecret; + }) + ); + } + + onImageChange = (value: string) => { + this.nodeShellImage = value; + }; + + onSecretChange = (value: string) => { + this.imagePullSecret = value; + }; + + saveImage = () => { + this.props.cluster.preferences.nodeShellImage = this.nodeShellImage; + }; + + saveSecret = () => { + this.props.cluster.preferences.imagePullSecret = this.imagePullSecret; + }; + + resetImage = () => { + this.nodeShellImage = initialNodeShellImage; //revert to default + }; + + clearSecret = () => { + this.imagePullSecret = ""; + }; + + render() { + + return ( + <> +
+ + } + /> + + Node shell image. Used for creating node shell pod. + +
+
+ + } + /> + + Name of a pre-existing secret (optional). Used for pulling image from a private registry. + +
+ + ); + } +} diff --git a/src/renderer/components/cluster-settings/components/index.ts b/src/renderer/components/cluster-settings/components/index.ts index e82425c9c7..beb80269b7 100644 --- a/src/renderer/components/cluster-settings/components/index.ts +++ b/src/renderer/components/cluster-settings/components/index.ts @@ -28,3 +28,4 @@ export * from "./cluster-prometheus-setting"; export * from "./cluster-proxy-setting"; export * from "./cluster-show-metrics"; export * from "./cluster-icon-settings"; +export * from "./cluster-node-shell-setting"; diff --git a/src/renderer/initializers/entity-settings-registry.ts b/src/renderer/initializers/entity-settings-registry.ts index 10723c8ebf..31c8c81c21 100644 --- a/src/renderer/initializers/entity-settings-registry.ts +++ b/src/renderer/initializers/entity-settings-registry.ts @@ -70,6 +70,15 @@ export function initEntitySettingsRegistry() { components: { View: clusterSettings.MetricsSettings, } + }, + { + apiVersions: ["entity.k8slens.dev/v1alpha1"], + kind: "KubernetesCluster", + title: "Node Shell", + group: "Settings", + components: { + View: clusterSettings.NodeShellSettings, + } } ]); }