UNPKG

@kinvolk/headlamp-plugin

Version:

The needed infrastructure for building Headlamp plugins.

123 lines (122 loc) 6.01 kB
import { jsx as _jsx } from "react/jsx-runtime"; /* * Copyright 2025 The Kubernetes Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Icon } from '@iconify/react'; import { useTheme } from '@mui/material/styles'; import Switch from '@mui/material/Switch'; import TextField from '@mui/material/TextField'; import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { DEFAULT_POD_DEBUG_IMAGE, loadClusterSettings, storeClusterSettings, } from '../../../helpers/clusterSettings'; import { HoverInfoLabel } from '../../common/Label'; import { NameValueTable } from '../../common/NameValueTable'; import SectionBox from '../../common/SectionBox'; /** * Settings component for pod debugging with ephemeral containers. * * Allows enabling/disabling debugging and configuring the default debug image per cluster. * Settings persist to localStorage and take effect immediately. * * @param props - Cluster name * @returns Settings section with debug controls */ export default function PodDebugSettings(props) { const { cluster } = props; const { t } = useTranslation(['translation']); const theme = useTheme(); const [clusterSettings, setClusterSettings] = useState(null); const [userImage, setUserImage] = useState(''); const [userIsEnabled, setUserIsEnabled] = useState(null); const podDebugLabelID = 'pod-debug-enabled-label'; useEffect(() => { setClusterSettings(!!cluster ? loadClusterSettings(cluster) : null); }, [cluster]); useEffect(() => { if (clusterSettings?.podDebugTerminal?.debugImage !== userImage) { setUserImage(clusterSettings?.podDebugTerminal?.debugImage ?? ''); } setUserIsEnabled(clusterSettings?.podDebugTerminal?.isEnabled ?? true); // Avoid re-initializing settings as {} just because the cluster is not yet set. if (clusterSettings !== null) { storeClusterSettings(cluster, clusterSettings); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [cluster, clusterSettings]); // eslint-disable-next-line react-hooks/exhaustive-deps function isEditingImage() { return clusterSettings?.podDebugTerminal?.debugImage !== userImage; } const storeNewImage = useCallback((image) => { let actualImage = image; if (image === DEFAULT_POD_DEBUG_IMAGE) { actualImage = ''; setUserImage(actualImage); } setClusterSettings((settings) => { const newSettings = { ...(settings || {}) }; if (newSettings.podDebugTerminal === null || newSettings.podDebugTerminal === undefined) { newSettings.podDebugTerminal = {}; } newSettings.podDebugTerminal.debugImage = actualImage; return newSettings; }); }, [setClusterSettings, setUserImage]); function storeNewEnabled(enabled) { setUserIsEnabled(enabled); setClusterSettings((settings) => { const newSettings = { ...(settings || {}) }; if (newSettings.podDebugTerminal === null || newSettings.podDebugTerminal === undefined) { newSettings.podDebugTerminal = {}; } newSettings.podDebugTerminal.isEnabled = enabled; return newSettings; }); } useEffect(() => { let timeoutHandle = null; if (isEditingImage()) { // We store the image after a timeout. timeoutHandle = setTimeout(() => { storeNewImage(userImage); }, 1000); } return () => { if (timeoutHandle) { clearTimeout(timeoutHandle); } }; }, [userImage, isEditingImage, storeNewImage]); return (_jsx(SectionBox, { title: t('translation|Pod Debug Settings'), headerProps: { headerStyle: 'label' }, children: _jsx(NameValueTable, { rows: [ { name: (_jsx(HoverInfoLabel, { label: _jsx("span", { id: podDebugLabelID, children: "Enable Pod Debug" }), hoverInfo: t('translation|Ephemeral debug containers cannot be removed via Kubernetes API. They will remain in the pod specification even after the terminal closes. To remove them, the pod must be recreated.') })), value: (_jsx(Switch, { inputProps: { 'aria-labelledby': podDebugLabelID }, checked: userIsEnabled ?? true, onChange: e => { const newEnabled = e.target.checked; storeNewEnabled(newEnabled); } })), }, { name: 'Debug Image', value: (_jsx(TextField, { onChange: event => { let value = event.target.value; value = value.replace(' ', ''); setUserImage(value); }, value: userImage, placeholder: DEFAULT_POD_DEBUG_IMAGE, helperText: t('translation|The default image is used for creating ephemeral debug containers.'), variant: "outlined", size: "small", InputProps: { endAdornment: isEditingImage() ? (_jsx(Icon, { width: 24, color: theme.palette.text.secondary, icon: "mdi:progress-check" })) : (_jsx(Icon, { width: 24, icon: "mdi:check-bold" })), sx: { maxWidth: 300 }, } })), }, ] }) })); }