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:
@@ -44,13 +44,26 @@ export const ProviderLabelMap = {
|
||||
};
|
||||
|
||||
export const generateK8sRegisterCommand = (params: {
|
||||
// Either a single GPU driver key (legacy single-select) or an array of
|
||||
// keys (multi-vendor mode). Both feed into a list of runtimes for the
|
||||
// ?runtime=... query parameters the backend accepts (repeatable).
|
||||
currentGPU?: string;
|
||||
currentGPUs?: string[];
|
||||
server: string;
|
||||
clusterId: number | null;
|
||||
registrationToken: string;
|
||||
}) => {
|
||||
const runtime = GPUsConfigs[params.currentGPU || '']?.runtime || '';
|
||||
return `curl -k -L '${params.server}/${GPUSTACK_API_BASE_URL}/clusters/${params.clusterId}/manifests${runtime ? `?runtime=${runtime}` : ''}' \\
|
||||
const keys =
|
||||
params.currentGPUs && params.currentGPUs.length > 0
|
||||
? params.currentGPUs
|
||||
: params.currentGPU
|
||||
? [params.currentGPU]
|
||||
: [];
|
||||
const runtimes = keys
|
||||
.map((k) => GPUsConfigs[k]?.runtime)
|
||||
.filter((r): r is string => !!r);
|
||||
const query = runtimes.map((r) => `runtime=${r}`).join('&');
|
||||
return `curl -k -L '${params.server}/${GPUSTACK_API_BASE_URL}/clusters/${params.clusterId}/manifests${query ? `?${query}` : ''}' \\
|
||||
--header 'Authorization: Bearer ${params.registrationToken}' | kubectl apply -f -`;
|
||||
};
|
||||
|
||||
|
||||
@@ -68,6 +68,25 @@ export interface VolumeMount {
|
||||
};
|
||||
}
|
||||
|
||||
export interface ImageCredential {
|
||||
registry: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface K8sOptions {
|
||||
// Backend serializes K8sOptions with camelCase aliases (by_alias=True on
|
||||
// the SQL JSON column). The top-level `k8s_options` field on the cluster
|
||||
// stays snake_case, but everything inside follows the backend wire shape.
|
||||
volumeMounts?: VolumeMount[];
|
||||
imageCredentials?: ImageCredential[];
|
||||
nodeSelector?: Record<string, string>;
|
||||
gpuVendorOverrides?: Record<
|
||||
string,
|
||||
{ nodeSelector?: Record<string, string> }
|
||||
>;
|
||||
}
|
||||
|
||||
export interface ClusterListItem {
|
||||
name: string;
|
||||
display_name: string;
|
||||
@@ -87,7 +106,7 @@ export interface ClusterListItem {
|
||||
state: ClusterStatusType;
|
||||
state_message: string;
|
||||
worker_pools: NodePoolListItem[];
|
||||
k8s_volume_mounts?: VolumeMount[];
|
||||
k8s_options?: K8sOptions;
|
||||
// Backend ClusterPublic carries this; admin-"All" namespace
|
||||
// resolution falls back to the cluster's owner Org name.
|
||||
owner_principal_id?: number;
|
||||
@@ -104,7 +123,7 @@ export interface ClusterFormData {
|
||||
server_url?: string;
|
||||
worker_config?: Record<string, any>;
|
||||
worker_pools?: NodePoolFormData[];
|
||||
k8s_volume_mounts?: VolumeMount[];
|
||||
k8s_options?: K8sOptions;
|
||||
}
|
||||
|
||||
export interface SystemConfig {
|
||||
|
||||
Reference in New Issue
Block a user