feat: extend cluster k8s_options with multi-vendor manifest support

- New k8s_pod_spec form sections (image credentials, node selector,
  gpu vendor overrides) under k8s_options, replacing the legacy flat
  k8s_volume_mounts list. UI keys aligned to the backend wire shape
  (snake_case k8s_options + camelCase inside).
- System default container registry is pre-filled into the first image
  credential when creating a new cluster; empty username/password are
  coerced to null on submit to match the Optional[str] backend schema.
- Register cluster flow supports multi-runtime selection gated by the
  cluster's gpuVendorOverrides: non-override vendors stay single-select
  with an inline hint; multi-add only opens once an override vendor is
  picked, and non-override cards become disabled in that state.
- Manifest URL emits multiple ?runtime= params; check-env step combines
  per-vendor commands; downstream steps are disabled when no vendor is
  selected.
- Pre-validate gpuVendorOverrides at save time (non-empty selector, no
  duplicates across vendors, no key clash with base nodeSelector) so
  the user sees the error before hitting the manifest endpoint.
- Misc: dark-mode background of the k8s_pod_spec / volume mount titles
  no longer clashes with the drawer; cluster Steps no longer leaks the
  internal showModules/showForms props to the DOM.
This commit is contained in:
Yuxing Deng
2026-05-26 16:54:14 +08:00
parent 91c3d0b814
commit acb90531b2
21 changed files with 1023 additions and 112 deletions
@@ -76,14 +76,19 @@ const ProviderImage = ({ src, height }: { src: string; height?: number }) => {
interface SupportedHardwareProps {
onSelect?: (provider: string, item: any) => void;
current?: string;
// Single (legacy) or array of selected GPU driver keys (multi-select).
current?: string | string[];
clickable?: boolean;
// Set of GPU driver keys that are valid to pick. When provided, items
// outside this set render as disabled. Undefined means "no restriction".
availableKeys?: Set<string>;
}
const SupportedHardware: React.FC<SupportedHardwareProps> = ({
onSelect,
clickable,
current
current,
availableKeys
}) => {
const intl = useIntl();
const { userSettings } = useUserSettings();
@@ -199,13 +204,20 @@ const SupportedHardware: React.FC<SupportedHardwareProps> = ({
}
];
const platformsWithDisabled = availableKeys
? supportedHardPlatforms.map((p) => ({
...p,
disabled: !availableKeys.has(p.value)
}))
: supportedHardPlatforms;
return (
<Box className={userSettings?.theme === 'realDark' ? 'dark-theme' : ''}>
<ProviderCatalog
onSelect={onSelect}
height={60}
current={current}
dataList={supportedHardPlatforms}
dataList={platformsWithDisabled}
clickable={clickable}
showTooltip={true}
cols={5}