feat(cluster): add default container registry field to advanced config
Surface the top-level system_default_container_registry as a dedicated input (both Docker and K8s), coerce blank to null, and drop its redundant worker_config YAML hint.
This commit is contained in:
@@ -162,6 +162,9 @@ export default {
|
|||||||
'clusters.volume.configMap.name': 'ConfigMap Name',
|
'clusters.volume.configMap.name': 'ConfigMap Name',
|
||||||
'clusters.volume.configMap.optional': 'Optional',
|
'clusters.volume.configMap.optional': 'Optional',
|
||||||
'clusters.volume.add': 'Add Volume Mount',
|
'clusters.volume.add': 'Add Volume Mount',
|
||||||
|
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
||||||
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
|
'Default registry used to resolve GPUStack images for this cluster. Falls back to the server default when unset.',
|
||||||
'clusters.k8sOptions.title': 'K8s Deployment Options',
|
'clusters.k8sOptions.title': 'K8s Deployment Options',
|
||||||
'clusters.imageCredentials.title': 'Image Credentials',
|
'clusters.imageCredentials.title': 'Image Credentials',
|
||||||
'clusters.imageCredentials.add': 'Add Credential',
|
'clusters.imageCredentials.add': 'Add Credential',
|
||||||
|
|||||||
@@ -162,6 +162,9 @@ export default {
|
|||||||
'clusters.volume.configMap.name': 'ConfigMap Name',
|
'clusters.volume.configMap.name': 'ConfigMap Name',
|
||||||
'clusters.volume.configMap.optional': 'Optional',
|
'clusters.volume.configMap.optional': 'Optional',
|
||||||
'clusters.volume.add': 'Add Volume Mount',
|
'clusters.volume.add': 'Add Volume Mount',
|
||||||
|
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
||||||
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
|
'Default registry used to resolve GPUStack images for this cluster. Falls back to the server default when unset.',
|
||||||
'clusters.k8sOptions.title': 'K8s Deployment Options',
|
'clusters.k8sOptions.title': 'K8s Deployment Options',
|
||||||
'clusters.imageCredentials.title': 'Image Credentials',
|
'clusters.imageCredentials.title': 'Image Credentials',
|
||||||
'clusters.imageCredentials.add': 'Add Credential',
|
'clusters.imageCredentials.add': 'Add Credential',
|
||||||
|
|||||||
@@ -163,6 +163,9 @@ export default {
|
|||||||
'clusters.volume.configMap.name': 'ConfigMap Name',
|
'clusters.volume.configMap.name': 'ConfigMap Name',
|
||||||
'clusters.volume.configMap.optional': 'Optional',
|
'clusters.volume.configMap.optional': 'Optional',
|
||||||
'clusters.volume.add': 'Add Volume Mount',
|
'clusters.volume.add': 'Add Volume Mount',
|
||||||
|
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
||||||
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
|
'Default registry used to resolve GPUStack images for this cluster. Falls back to the server default when unset.',
|
||||||
'clusters.k8sOptions.title': 'K8s Deployment Options',
|
'clusters.k8sOptions.title': 'K8s Deployment Options',
|
||||||
'clusters.imageCredentials.title': 'Image Credentials',
|
'clusters.imageCredentials.title': 'Image Credentials',
|
||||||
'clusters.imageCredentials.add': 'Add Credential',
|
'clusters.imageCredentials.add': 'Add Credential',
|
||||||
|
|||||||
@@ -163,6 +163,9 @@ export default {
|
|||||||
'clusters.volume.configMap.name': 'ConfigMap Name',
|
'clusters.volume.configMap.name': 'ConfigMap Name',
|
||||||
'clusters.volume.configMap.optional': 'Optional',
|
'clusters.volume.configMap.optional': 'Optional',
|
||||||
'clusters.volume.add': 'Add Volume Mount',
|
'clusters.volume.add': 'Add Volume Mount',
|
||||||
|
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
||||||
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
|
'Default registry used to resolve GPUStack images for this cluster. Falls back to the server default when unset.',
|
||||||
'clusters.k8sOptions.title': 'K8s Deployment Options',
|
'clusters.k8sOptions.title': 'K8s Deployment Options',
|
||||||
'clusters.imageCredentials.title': 'Image Credentials',
|
'clusters.imageCredentials.title': 'Image Credentials',
|
||||||
'clusters.imageCredentials.add': 'Add Credential',
|
'clusters.imageCredentials.add': 'Add Credential',
|
||||||
|
|||||||
@@ -155,6 +155,9 @@ export default {
|
|||||||
'clusters.volume.configMap.name': '配置名称',
|
'clusters.volume.configMap.name': '配置名称',
|
||||||
'clusters.volume.configMap.optional': '可选',
|
'clusters.volume.configMap.optional': '可选',
|
||||||
'clusters.volume.add': '添加卷挂载',
|
'clusters.volume.add': '添加卷挂载',
|
||||||
|
'clusters.systemDefaultContainerRegistry.title': '默认容器镜像仓库',
|
||||||
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
|
'用于解析该集群 GPUStack 镜像的默认镜像仓库。未设置时回退到服务端默认值。',
|
||||||
'clusters.k8sOptions.title': 'K8s 部署选项',
|
'clusters.k8sOptions.title': 'K8s 部署选项',
|
||||||
'clusters.imageCredentials.title': '镜像仓库凭证',
|
'clusters.imageCredentials.title': '镜像仓库凭证',
|
||||||
'clusters.imageCredentials.add': '添加凭证',
|
'clusters.imageCredentials.add': '添加凭证',
|
||||||
|
|||||||
@@ -64,8 +64,18 @@ const ClusterForm: React.FC<AddModalProps> = forwardRef(
|
|||||||
// "no auth". Coerce empty form values to null before sending so a blank
|
// "no auth". Coerce empty form values to null before sending so a blank
|
||||||
// input is unambiguous rather than an empty string that defeats fallbacks.
|
// input is unambiguous rather than an empty string that defeats fallbacks.
|
||||||
const normalizeOutgoing = (values: any): any => {
|
const normalizeOutgoing = (values: any): any => {
|
||||||
const opts = values?.k8s_options;
|
const base: any = { ...values };
|
||||||
if (!opts) return values;
|
// Top-level cluster field shared by Docker and K8s. Trim then coerce a
|
||||||
|
// blank input to null so clearing it on edit (or a whitespace-only
|
||||||
|
// value) falls back to the server default rather than persisting an
|
||||||
|
// empty string.
|
||||||
|
if (base.system_default_container_registry !== undefined) {
|
||||||
|
base.system_default_container_registry =
|
||||||
|
base.system_default_container_registry?.trim() || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const opts = base.k8s_options;
|
||||||
|
if (!opts) return base;
|
||||||
|
|
||||||
const next: any = { ...opts };
|
const next: any = { ...opts };
|
||||||
|
|
||||||
@@ -90,7 +100,7 @@ const ClusterForm: React.FC<AddModalProps> = forwardRef(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ...values, k8s_options: next };
|
return { ...base, k8s_options: next };
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOnFinish = (_values: FormData) => {
|
const handleOnFinish = (_values: FormData) => {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ export const dockerConfig = `# This is a template for worker_config.
|
|||||||
|
|
||||||
# ========= container & image ===========
|
# ========= container & image ===========
|
||||||
|
|
||||||
# system_default_container_registry: "docker.io"
|
|
||||||
# image_name_override: "gpustack/gpustack:dev"
|
# image_name_override: "gpustack/gpustack:dev"
|
||||||
# image_repo: "gpustack/gpustack"
|
# image_repo: "gpustack/gpustack"
|
||||||
|
|
||||||
@@ -53,7 +52,6 @@ export const kubernetesConfig = `# This is a template for worker_config.
|
|||||||
|
|
||||||
# ========= container & image ===========
|
# ========= container & image ===========
|
||||||
|
|
||||||
# system_default_container_registry: "docker.io"
|
|
||||||
# image_name_override: "gpustack/gpustack:dev"
|
# image_name_override: "gpustack/gpustack:dev"
|
||||||
# image_repo: "gpustack/gpustack"
|
# image_repo: "gpustack/gpustack"
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,24 @@ const ClusterAdvanceConfig: React.FC<{
|
|||||||
>
|
>
|
||||||
<CInput.TextArea required={false} trim={false}></CInput.TextArea>
|
<CInput.TextArea required={false} trim={false}></CInput.TextArea>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
{/* Default container registry used to resolve images for this cluster.
|
||||||
|
A top-level cluster field shared by both Docker and Kubernetes
|
||||||
|
providers (the backend hoists any legacy worker_config value onto
|
||||||
|
this column). */}
|
||||||
|
<Form.Item<FormData>
|
||||||
|
name="system_default_container_registry"
|
||||||
|
style={{ marginBottom: 16 }}
|
||||||
|
>
|
||||||
|
<CInput.Input
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'clusters.systemDefaultContainerRegistry.title'
|
||||||
|
})}
|
||||||
|
description={intl.formatMessage({
|
||||||
|
id: 'clusters.systemDefaultContainerRegistry.tip'
|
||||||
|
})}
|
||||||
|
placeholder="docker.io"
|
||||||
|
></CInput.Input>
|
||||||
|
</Form.Item>
|
||||||
<Title>
|
<Title>
|
||||||
{intl.formatMessage({ id: 'clusters.create.workerConfig' })}
|
{intl.formatMessage({ id: 'clusters.create.workerConfig' })}
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
Reference in New Issue
Block a user