chore: ssh key selection
This commit is contained in:
@@ -4,3 +4,7 @@ import { atom } from 'jotai';
|
|||||||
export const currentClusterAtom = atom<
|
export const currentClusterAtom = atom<
|
||||||
(Partial<ClusterListItem> & { label?: string; value?: number }) | null
|
(Partial<ClusterListItem> & { label?: string; value?: number }) | null
|
||||||
>(null);
|
>(null);
|
||||||
|
|
||||||
|
export const addSSHKeyPageAtom = atom<{ create: boolean }>({
|
||||||
|
create: false
|
||||||
|
});
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ export default {
|
|||||||
'gpuservice.template.card.resources': 'Resources',
|
'gpuservice.template.card.resources': 'Resources',
|
||||||
'gpuservice.template.card.ports': 'Ports',
|
'gpuservice.template.card.ports': 'Ports',
|
||||||
'gpuservice.publicKey.label': 'SSH Public Key',
|
'gpuservice.publicKey.label': 'SSH Public Key',
|
||||||
|
'gpuservice.instance.ssh.enable': 'Enable SSH Access',
|
||||||
|
'gpuservice.instance.ssh.assignKey': 'Assign SSH Public Key',
|
||||||
|
'gpuservice.instance.ssh.addKey': 'Add SSH Public Key',
|
||||||
'gpuservice.publicKey.placeholder':
|
'gpuservice.publicKey.placeholder':
|
||||||
'Begin with ssh-rsa or ssh-ed25519. One Public Key per line.\n\nView Public Key:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
'Begin with ssh-rsa or ssh-ed25519. One Public Key per line.\n\nView Public Key:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
||||||
'gpuservice.instance': 'GPU Instance',
|
'gpuservice.instance': 'GPU Instance',
|
||||||
|
|||||||
@@ -64,5 +64,9 @@ export default {
|
|||||||
'noresult.gpuservice.instance.nofound': 'No matching GPU instances found.',
|
'noresult.gpuservice.instance.nofound': 'No matching GPU instances found.',
|
||||||
'noresult.gpuservice.storage.title': 'No Storage',
|
'noresult.gpuservice.storage.title': 'No Storage',
|
||||||
'noresult.gpuservice.storage.subTitle': 'No storage has been added yet.',
|
'noresult.gpuservice.storage.subTitle': 'No storage has been added yet.',
|
||||||
'noresult.gpuservice.storage.nofound': 'No matching storage found.'
|
'noresult.gpuservice.storage.nofound': 'No matching storage found.',
|
||||||
|
'noresult.gpuservice.sshkey.title': 'No SSH Public Keys',
|
||||||
|
'noresult.gpuservice.sshkey.subTitle':
|
||||||
|
'No SSH public keys have been added yet.',
|
||||||
|
'noresult.gpuservice.sshkey.nofound': 'No matching SSH public keys found.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ export default {
|
|||||||
'gpuservice.template.card.resources': 'リソース',
|
'gpuservice.template.card.resources': 'リソース',
|
||||||
'gpuservice.template.card.ports': 'ポート',
|
'gpuservice.template.card.ports': 'ポート',
|
||||||
'gpuservice.publicKey.label': 'SSH 公開鍵',
|
'gpuservice.publicKey.label': 'SSH 公開鍵',
|
||||||
|
'gpuservice.instance.ssh.enable': 'SSH アクセスを有効化',
|
||||||
|
'gpuservice.instance.ssh.assignKey': 'SSH 公開鍵を割り当て',
|
||||||
|
'gpuservice.instance.ssh.addKey': 'SSH 公開鍵を追加',
|
||||||
'gpuservice.publicKey.placeholder':
|
'gpuservice.publicKey.placeholder':
|
||||||
'ssh-rsa または ssh-ed25519 で始まり、各公開鍵は1行ずつ記述します\n\n公開鍵を確認:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
'ssh-rsa または ssh-ed25519 で始まり、各公開鍵は1行ずつ記述します\n\n公開鍵を確認:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
||||||
'gpuservice.instance': 'GPU インスタンス',
|
'gpuservice.instance': 'GPU インスタンス',
|
||||||
|
|||||||
@@ -66,5 +66,8 @@ export default {
|
|||||||
'noresult.gpuservice.storage.title': 'ストレージなし',
|
'noresult.gpuservice.storage.title': 'ストレージなし',
|
||||||
'noresult.gpuservice.storage.subTitle':
|
'noresult.gpuservice.storage.subTitle':
|
||||||
'ストレージはまだ追加されていません。',
|
'ストレージはまだ追加されていません。',
|
||||||
'noresult.gpuservice.storage.nofound': '一致するストレージが見つかりません。'
|
'noresult.gpuservice.storage.nofound': '一致するストレージが見つかりません。',
|
||||||
|
'noresult.gpuservice.sshkey.title': 'SSH 公開鍵なし',
|
||||||
|
'noresult.gpuservice.sshkey.subTitle': 'SSH 公開鍵はまだ追加されていません。',
|
||||||
|
'noresult.gpuservice.sshkey.nofound': '一致する SSH 公開鍵が見つかりません。'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ export default {
|
|||||||
'gpuservice.template.card.resources': 'Ресурсы',
|
'gpuservice.template.card.resources': 'Ресурсы',
|
||||||
'gpuservice.template.card.ports': 'Порты',
|
'gpuservice.template.card.ports': 'Порты',
|
||||||
'gpuservice.publicKey.label': 'Открытый ключ SSH',
|
'gpuservice.publicKey.label': 'Открытый ключ SSH',
|
||||||
|
'gpuservice.instance.ssh.enable': 'Включить SSH-доступ',
|
||||||
|
'gpuservice.instance.ssh.assignKey': 'Назначить открытый ключ SSH',
|
||||||
|
'gpuservice.instance.ssh.addKey': 'Добавить открытый ключ SSH',
|
||||||
'gpuservice.publicKey.placeholder':
|
'gpuservice.publicKey.placeholder':
|
||||||
'Начинается с ssh-rsa или ssh-ed25519, по одному открытому ключу на строку\n\nПросмотр открытого ключа:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
'Начинается с ssh-rsa или ssh-ed25519, по одному открытому ключу на строку\n\nПросмотр открытого ключа:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
||||||
'gpuservice.instance': 'Экземпляр GPU',
|
'gpuservice.instance': 'Экземпляр GPU',
|
||||||
|
|||||||
@@ -65,7 +65,11 @@ export default {
|
|||||||
'Подходящие экземпляры GPU не найдены.',
|
'Подходящие экземпляры GPU не найдены.',
|
||||||
'noresult.gpuservice.storage.title': 'Нет хранилищ',
|
'noresult.gpuservice.storage.title': 'Нет хранилищ',
|
||||||
'noresult.gpuservice.storage.subTitle': 'Хранилища ещё не добавлены.',
|
'noresult.gpuservice.storage.subTitle': 'Хранилища ещё не добавлены.',
|
||||||
'noresult.gpuservice.storage.nofound': 'Подходящие хранилища не найдены.'
|
'noresult.gpuservice.storage.nofound': 'Подходящие хранилища не найдены.',
|
||||||
|
'noresult.gpuservice.sshkey.title': 'Нет открытых ключей SSH',
|
||||||
|
'noresult.gpuservice.sshkey.subTitle': 'Открытые ключи SSH ещё не добавлены.',
|
||||||
|
'noresult.gpuservice.sshkey.nofound':
|
||||||
|
'Подходящие открытые ключи SSH не найдены.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ export default {
|
|||||||
'gpuservice.template.card.resources': 'Kaynaklar',
|
'gpuservice.template.card.resources': 'Kaynaklar',
|
||||||
'gpuservice.template.card.ports': 'Bağlantı Noktaları',
|
'gpuservice.template.card.ports': 'Bağlantı Noktaları',
|
||||||
'gpuservice.publicKey.label': 'SSH Açık Anahtarı',
|
'gpuservice.publicKey.label': 'SSH Açık Anahtarı',
|
||||||
|
'gpuservice.instance.ssh.enable': 'SSH Erişimini Etkinleştir',
|
||||||
|
'gpuservice.instance.ssh.assignKey': 'SSH Açık Anahtarı Ata',
|
||||||
|
'gpuservice.instance.ssh.addKey': 'SSH Açık Anahtarı Ekle',
|
||||||
'gpuservice.publicKey.placeholder':
|
'gpuservice.publicKey.placeholder':
|
||||||
'ssh-rsa veya ssh-ed25519 ile başlar, her açık anahtar ayrı bir satırda\n\nAçık anahtarı görüntüle:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
'ssh-rsa veya ssh-ed25519 ile başlar, her açık anahtar ayrı bir satırda\n\nAçık anahtarı görüntüle:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
||||||
'gpuservice.instance': 'GPU Örneği',
|
'gpuservice.instance': 'GPU Örneği',
|
||||||
|
|||||||
@@ -63,7 +63,10 @@ export default {
|
|||||||
'noresult.gpuservice.instance.nofound': 'Eşleşen GPU örneği bulunamadı.',
|
'noresult.gpuservice.instance.nofound': 'Eşleşen GPU örneği bulunamadı.',
|
||||||
'noresult.gpuservice.storage.title': 'Depolama Yok',
|
'noresult.gpuservice.storage.title': 'Depolama Yok',
|
||||||
'noresult.gpuservice.storage.subTitle': 'Henüz depolama eklenmedi.',
|
'noresult.gpuservice.storage.subTitle': 'Henüz depolama eklenmedi.',
|
||||||
'noresult.gpuservice.storage.nofound': 'Eşleşen depolama bulunamadı.'
|
'noresult.gpuservice.storage.nofound': 'Eşleşen depolama bulunamadı.',
|
||||||
|
'noresult.gpuservice.sshkey.title': 'SSH Açık Anahtarı Yok',
|
||||||
|
'noresult.gpuservice.sshkey.subTitle': 'Henüz SSH açık anahtarı eklenmedi.',
|
||||||
|
'noresult.gpuservice.sshkey.nofound': 'Eşleşen SSH açık anahtarı bulunamadı.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ export default {
|
|||||||
'gpuservice.template.card.resources': '资源',
|
'gpuservice.template.card.resources': '资源',
|
||||||
'gpuservice.template.card.ports': '端口',
|
'gpuservice.template.card.ports': '端口',
|
||||||
'gpuservice.publicKey.label': 'SSH 公钥',
|
'gpuservice.publicKey.label': 'SSH 公钥',
|
||||||
|
'gpuservice.instance.ssh.enable': '启用 SSH 访问',
|
||||||
|
'gpuservice.instance.ssh.assignKey': '分配 SSH 公钥',
|
||||||
|
'gpuservice.instance.ssh.addKey': '添加 SSH 公钥',
|
||||||
'gpuservice.publicKey.placeholder':
|
'gpuservice.publicKey.placeholder':
|
||||||
'以 ssh-rsa 或 ssh-ed25519 开头,每个公钥单独一行\n\n查看公钥:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
'以 ssh-rsa 或 ssh-ed25519 开头,每个公钥单独一行\n\n查看公钥:\n- RSA\ncat ~/.ssh/id_rsa.pub\n- Ed25519\ncat ~/.ssh/id_ed25519.pub',
|
||||||
'gpuservice.instance': 'GPU 实例',
|
'gpuservice.instance': 'GPU 实例',
|
||||||
|
|||||||
@@ -59,5 +59,8 @@ export default {
|
|||||||
'noresult.gpuservice.instance.nofound': '未找到匹配的 GPU 实例',
|
'noresult.gpuservice.instance.nofound': '未找到匹配的 GPU 实例',
|
||||||
'noresult.gpuservice.storage.title': '暂无存储',
|
'noresult.gpuservice.storage.title': '暂无存储',
|
||||||
'noresult.gpuservice.storage.subTitle': '尚未添加任何存储。',
|
'noresult.gpuservice.storage.subTitle': '尚未添加任何存储。',
|
||||||
'noresult.gpuservice.storage.nofound': '未找到匹配的存储'
|
'noresult.gpuservice.storage.nofound': '未找到匹配的存储',
|
||||||
|
'noresult.gpuservice.sshkey.title': '暂无 SSH 公钥',
|
||||||
|
'noresult.gpuservice.sshkey.subTitle': '尚未添加任何 SSH 公钥。',
|
||||||
|
'noresult.gpuservice.sshkey.nofound': '未找到匹配的 SSH 公钥'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
|
import { addSSHKeyPageAtom } from '@/atoms/gpuservice';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
import { PageActionType } from '@/config/types';
|
import { PageActionType } from '@/config/types';
|
||||||
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
import {
|
import {
|
||||||
CheckboxField,
|
CheckboxField,
|
||||||
CollapsePanel,
|
CollapsePanel,
|
||||||
IconFont,
|
IconFont,
|
||||||
MultipleSelect,
|
MultipleSelect,
|
||||||
ScrollSpyTabs,
|
ScrollSpyTabs,
|
||||||
|
useAppUtils,
|
||||||
useFinishFailed,
|
useFinishFailed,
|
||||||
useScrollActiveChange,
|
useScrollActiveChange,
|
||||||
useWrapperContext
|
useWrapperContext
|
||||||
} from '@gpustack/core-ui';
|
} from '@gpustack/core-ui';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl, useNavigate } from '@umijs/max';
|
||||||
import { Form } from 'antd';
|
import { Button, Empty, Form } from 'antd';
|
||||||
|
import { useSetAtom } from 'jotai';
|
||||||
import {
|
import {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
useEffect,
|
useEffect,
|
||||||
@@ -96,6 +100,9 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
|||||||
onFinish
|
onFinish
|
||||||
} = props;
|
} = props;
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const setAddSSHKeyPage = useSetAtom(addSSHKeyPageAtom);
|
||||||
|
const { getRuleMessage } = useAppUtils();
|
||||||
const [form] = Form.useForm<InstanceFormValues>();
|
const [form] = Form.useForm<InstanceFormValues>();
|
||||||
const scrollTabsRef = useRef<any>(null);
|
const scrollTabsRef = useRef<any>(null);
|
||||||
const formAction =
|
const formAction =
|
||||||
@@ -278,6 +285,12 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
|||||||
getFieldsValue: () => form.getFieldsValue()
|
getFieldsValue: () => form.getFieldsValue()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const handleAddSSHKey = () => {
|
||||||
|
setAddSSHKeyPage({ create: true });
|
||||||
|
// to go ssh key page
|
||||||
|
navigate('/gpu-service/public-keys');
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollSpyTabs
|
<ScrollSpyTabs
|
||||||
ref={scrollTabsRef}
|
ref={scrollTabsRef}
|
||||||
@@ -308,9 +321,6 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
|||||||
resources: {
|
resources: {
|
||||||
accelerator: '1'
|
accelerator: '1'
|
||||||
},
|
},
|
||||||
sshPublicKey: {
|
|
||||||
name: 'gpustack-ssh-public-key'
|
|
||||||
},
|
|
||||||
volume: {
|
volume: {
|
||||||
ephemeral: {
|
ephemeral: {
|
||||||
capacity: '20Gi'
|
capacity: '20Gi'
|
||||||
@@ -379,37 +389,70 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
|||||||
>
|
>
|
||||||
<CheckboxField
|
<CheckboxField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
label={'启用 SSH 访问'}
|
label={intl.formatMessage({
|
||||||
|
id: 'gpuservice.instance.ssh.enable'
|
||||||
|
})}
|
||||||
onChange={handleSSHEnableChange}
|
onChange={handleSSHEnableChange}
|
||||||
></CheckboxField>
|
></CheckboxField>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{sshEnabled && (
|
{sshEnabled && (
|
||||||
<div className={instanceStyles.sshkeySelection}>
|
<div className={instanceStyles.sshkeySelection}>
|
||||||
<Form.Item<FormData> name={['spec', 'sshPublicKey', 'name']}>
|
<Form.Item<FormData>
|
||||||
|
name={['spec', 'sshPublicKey', 'name']}
|
||||||
|
style={{
|
||||||
|
marginBottom: 12
|
||||||
|
}}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: getRuleMessage(
|
||||||
|
'select',
|
||||||
|
'gpuservice.instance.ssh.assignKey'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
<MultipleSelect
|
<MultipleSelect
|
||||||
|
required
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
maxTagCount={1}
|
maxTagCount={1}
|
||||||
label={'SSH 公钥'}
|
label={intl.formatMessage({
|
||||||
|
id: 'gpuservice.instance.ssh.assignKey'
|
||||||
|
})}
|
||||||
styles={{
|
styles={{
|
||||||
wrapper: {
|
wrapper: {
|
||||||
width: '100%'
|
width: '100%'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
options={[
|
options={[]}
|
||||||
{
|
notFoundContent={
|
||||||
label: 'SSH-key-1',
|
<Empty
|
||||||
value: 'gpustack-ssh-public-key'
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
},
|
description={intl.formatMessage({
|
||||||
{
|
id: 'noresult.gpuservice.sshkey.title'
|
||||||
label: 'SSH-key-2',
|
})}
|
||||||
value: 'gpustack-ssh-public-key-2'
|
styles={{
|
||||||
},
|
image: {
|
||||||
{
|
height: 32
|
||||||
label: 'SSH-key-3',
|
},
|
||||||
value: 'gpustack-ssh-public-key-3'
|
root: {
|
||||||
}
|
margin: 0
|
||||||
]}
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
type="link"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={handleAddSSHKey}
|
||||||
|
>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: 'gpuservice.instance.ssh.addKey'
|
||||||
|
})}
|
||||||
|
</Button>
|
||||||
|
</Empty>
|
||||||
|
}
|
||||||
></MultipleSelect>
|
></MultipleSelect>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ const InstanceTypeFormItem: React.FC<InstanceTypeFormItemProps> = ({
|
|||||||
<InstanceTypePicker dataList={dataList} value={typeName} />
|
<InstanceTypePicker dataList={dataList} value={typeName} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</FieldBlock>
|
</FieldBlock>
|
||||||
{!selectedInstanceType?.spec?.acceleratable && (
|
{selectedInstanceType?.spec?.acceleratable && (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={['spec', 'resources', 'accelerator']}
|
name={['spec', 'resources', 'accelerator']}
|
||||||
rules={[
|
rules={[
|
||||||
|
|||||||
Reference in New Issue
Block a user