diff --git a/frontend/providers/dbprovider/public/locales/en/common.json b/frontend/providers/dbprovider/public/locales/en/common.json index 8b298ca7861..0837970773a 100644 --- a/frontend/providers/dbprovider/public/locales/en/common.json +++ b/frontend/providers/dbprovider/public/locales/en/common.json @@ -259,5 +259,8 @@ "Failed to turn off automatic backup": "Failed to turn off automatic backup", "Automatic backup is turned off": "Automatic backup is turned off", "Are you sure you want to turn off automatic backup": "Are you sure you want to turn off automatic backup?", - "db instances tip": "The number of {{db}} instances is recommended to be an odd number" + "db instances tip": "The number of {{db}} instances is recommended to be an odd number", + "Deleting": "Deleting", + "Backup Running": "Backup Running", + "Backup Deleting": "Backup Deleting" } \ No newline at end of file diff --git a/frontend/providers/dbprovider/public/locales/zh/common.json b/frontend/providers/dbprovider/public/locales/zh/common.json index 66b9d75208c..fea70999236 100644 --- a/frontend/providers/dbprovider/public/locales/zh/common.json +++ b/frontend/providers/dbprovider/public/locales/zh/common.json @@ -261,5 +261,8 @@ "Failed to turn off automatic backup": "关闭自动备份失败", "Automatic backup is turned off": "已关闭自动备份", "Are you sure you want to turn off automatic backup": "确定关闭自动备份吗", - "db instances tip": "{{db}} 实例数量建议为奇数" + "db instances tip": "{{db}} 实例数量建议为奇数", + "Deleting": "删除中", + "Backup Running": "备份中", + "Backup Deleting": "删除中" } \ No newline at end of file diff --git a/frontend/providers/dbprovider/src/constants/backup.ts b/frontend/providers/dbprovider/src/constants/backup.ts index d994e9f98a2..0e3702ddea3 100644 --- a/frontend/providers/dbprovider/src/constants/backup.ts +++ b/frontend/providers/dbprovider/src/constants/backup.ts @@ -3,8 +3,10 @@ import { BackupStatusMapType } from '@/types/db'; export enum BackupStatusEnum { Completed = 'Completed', InProgress = 'InProgress', - 'Failed' = 'Failed', - 'UnKnow' = 'UnKnow' + Failed = 'Failed', + UnKnow = 'UnKnow', + Running = 'Running', + Deleting = 'Deleting' } export const backupStatusMap: Record<`${BackupStatusEnum}`, BackupStatusMapType> = { @@ -23,6 +25,16 @@ export const backupStatusMap: Record<`${BackupStatusEnum}`, BackupStatusMapType> value: BackupStatusEnum.Failed, color: '#FF5B6E' }, + [BackupStatusEnum.Running]: { + label: 'Backup Running', + value: BackupStatusEnum.Running, + color: '#13B2A9' + }, + [BackupStatusEnum.Deleting]: { + label: 'Backup Deleting', + value: BackupStatusEnum.Deleting, + color: '#FF5B6E' + }, [BackupStatusEnum.UnKnow]: { label: 'UnKnow', value: BackupStatusEnum.UnKnow, diff --git a/frontend/providers/dbprovider/src/constants/db.ts b/frontend/providers/dbprovider/src/constants/db.ts index dd664c5be02..c365d6a7a4a 100644 --- a/frontend/providers/dbprovider/src/constants/db.ts +++ b/frontend/providers/dbprovider/src/constants/db.ts @@ -4,6 +4,7 @@ import { CpuSlideMarkList, MemorySlideMarkList } from './editApp'; export const crLabelKey = 'sealos-db-provider-cr'; export const CloudMigraionLabel = 'sealos-db-provider-cr-migrate'; export const KBMigrationTaskLabel = 'datamigration.apecloud.io/migrationtask'; +export const KBBackupNameLabel = 'dataprotection.kubeblocks.io/backup-name'; export const SealosMigrationTaskLabel = 'datamigration.sealos.io/file-migration-task'; export const MigrationRemark = 'migration-remark'; @@ -15,7 +16,8 @@ export enum DBTypeEnum { kafka = 'kafka', qdrant = 'qdrant', nebula = 'nebula', - weaviate = 'weaviate' + weaviate = 'weaviate', + milvus = 'milvus' } export enum DBStatusEnum { @@ -31,7 +33,8 @@ export enum DBStatusEnum { VerticalScaling = 'VerticalScaling', VolumeExpanding = 'VolumeExpanding', Failed = 'Failed', - UnKnow = 'UnKnow' + UnKnow = 'UnKnow', + Deleting = 'Deleting' } export const dbStatusMap = { [DBStatusEnum.Creating]: { @@ -124,6 +127,13 @@ export const dbStatusMap = { color: '#787A90', backgroundColor: '#F5F5F8', dotColor: '#787A90' + }, + [DBStatusEnum.Deleting]: { + label: 'Deleting', + value: DBStatusEnum.Deleting, + color: '#DC6803', + backgroundColor: '#FFFAEB', + dotColor: '#DC6803' } }; @@ -160,7 +170,8 @@ export const DBTypeList = [ { id: DBTypeEnum.mongodb, label: 'mongo' }, { id: DBTypeEnum.mysql, label: 'mysql' }, { id: DBTypeEnum.redis, label: 'redis' }, - { id: DBTypeEnum.kafka, label: 'kafka' } + { id: DBTypeEnum.kafka, label: 'kafka' }, + { id: DBTypeEnum.milvus, label: 'milvus' } // { id: DBTypeEnum.qdrant, label: 'qdrant' }, // { id: DBTypeEnum.nebula, label: 'nebula' }, // { id: DBTypeEnum.weaviate, label: 'weaviate' } @@ -174,7 +185,8 @@ export const DBComponentNameMap = { [DBTypeEnum.kafka]: 'kafka', [DBTypeEnum.qdrant]: 'qdrant', [DBTypeEnum.nebula]: 'nebula', - [DBTypeEnum.weaviate]: 'weaviate' + [DBTypeEnum.weaviate]: 'weaviate', + [DBTypeEnum.milvus]: 'milvus' }; export const DBBackupPolicyNameMap = { @@ -185,7 +197,21 @@ export const DBBackupPolicyNameMap = { [DBTypeEnum.kafka]: 'kafka', [DBTypeEnum.qdrant]: 'qdrant', [DBTypeEnum.nebula]: 'nebula', - [DBTypeEnum.weaviate]: 'weaviate' + [DBTypeEnum.weaviate]: 'weaviate', + [DBTypeEnum.milvus]: 'milvus' +}; + +export const DBBackupMethodNameMap = { + [DBTypeEnum.postgresql]: 'pg-basebackup', + [DBTypeEnum.mongodb]: 'dump', + [DBTypeEnum.mysql]: 'xtrabackup', + [DBTypeEnum.redis]: 'datafile', + // not support + [DBTypeEnum.kafka]: 'kafka', + [DBTypeEnum.qdrant]: 'qdrant', + [DBTypeEnum.nebula]: 'nebula', + [DBTypeEnum.weaviate]: 'weaviate', + [DBTypeEnum.milvus]: 'milvus' }; export const defaultDBEditValue: DBEditType = { @@ -259,5 +285,8 @@ export const DBTypeSecretMap = { }, weaviate: { connectKey: 'weaviate' + }, + milvus: { + connectKey: 'milvus' } }; diff --git a/frontend/providers/dbprovider/src/pages/api/backup/create.ts b/frontend/providers/dbprovider/src/pages/api/backup/create.ts index b537ca3d54e..953e5c70c66 100644 --- a/frontend/providers/dbprovider/src/pages/api/backup/create.ts +++ b/frontend/providers/dbprovider/src/pages/api/backup/create.ts @@ -4,7 +4,7 @@ import { authSession } from '@/services/backend/auth'; import { getK8s } from '@/services/backend/kubernetes'; import { jsonRes } from '@/services/backend/response'; import { json2ManualBackup } from '@/utils/json2Yaml'; -import { DBBackupPolicyNameMap, DBTypeEnum } from '@/constants/db'; +import { DBBackupMethodNameMap, DBBackupPolicyNameMap, DBTypeEnum } from '@/constants/db'; export type Props = { backupName: string; @@ -34,15 +34,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< }); // get backup backupolicies.dataprotection.kubeblocks.io - const { body } = (await k8sCustomObjects.getNamespacedCustomObject( - group, - version, - namespace, - plural, - `${dbName}-${DBBackupPolicyNameMap[dbType]}-backup-policy` - )) as { body: any }; + // const { body } = (await k8sCustomObjects.getNamespacedCustomObject( + // group, + // version, + // namespace, + // plural, + // `${dbName}-${DBBackupPolicyNameMap[dbType]}-backup-policy` + // )) as { body: any }; - const backupPolicyName = body?.metadata?.name; + const backupPolicyName = `${dbName}-${DBBackupPolicyNameMap[dbType]}-backup-policy`; + const backupMethod = DBBackupMethodNameMap[dbType]; if (!backupPolicyName) { throw new Error('Cannot find backup policy'); @@ -51,9 +52,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< const backupCr = json2ManualBackup({ name: backupName, backupPolicyName, + backupMethod, remark }); + console.info(backupCr); + // create backup await applyYamlList([backupCr], 'create'); diff --git a/frontend/providers/dbprovider/src/pages/api/getSecretByName.ts b/frontend/providers/dbprovider/src/pages/api/getSecretByName.ts index 4d349b9285d..df52c58f01c 100644 --- a/frontend/providers/dbprovider/src/pages/api/getSecretByName.ts +++ b/frontend/providers/dbprovider/src/pages/api/getSecretByName.ts @@ -69,6 +69,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< [DBTypeEnum.weaviate]: { ...base, connectKey: 'weaviate' + }, + [DBTypeEnum.milvus]: { + ...base, + connectKey: 'milvus' } }; // get secret diff --git a/frontend/providers/dbprovider/src/pages/api/getStatefulSetByName.ts b/frontend/providers/dbprovider/src/pages/api/getStatefulSetByName.ts index c9e56c6ad74..f24f0d1df50 100644 --- a/frontend/providers/dbprovider/src/pages/api/getStatefulSetByName.ts +++ b/frontend/providers/dbprovider/src/pages/api/getStatefulSetByName.ts @@ -41,6 +41,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< }, [DBTypeEnum.weaviate]: { key: 'weaviate' + }, + [DBTypeEnum.milvus]: { + key: 'milvus' } }; diff --git a/frontend/providers/dbprovider/src/pages/api/platform/getVersion.ts b/frontend/providers/dbprovider/src/pages/api/platform/getVersion.ts index e548da39cb8..cb2794da76c 100644 --- a/frontend/providers/dbprovider/src/pages/api/platform/getVersion.ts +++ b/frontend/providers/dbprovider/src/pages/api/platform/getVersion.ts @@ -25,7 +25,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) [DBTypeEnum.kafka]: [], [DBTypeEnum.qdrant]: [], [DBTypeEnum.nebula]: [], - [DBTypeEnum.weaviate]: [] + [DBTypeEnum.weaviate]: [], + [DBTypeEnum.milvus]: [] }; // source price diff --git a/frontend/providers/dbprovider/src/pages/api/pod/getPodsByDBName.ts b/frontend/providers/dbprovider/src/pages/api/pod/getPodsByDBName.ts index 3af049fca43..a5f34939155 100644 --- a/frontend/providers/dbprovider/src/pages/api/pod/getPodsByDBName.ts +++ b/frontend/providers/dbprovider/src/pages/api/pod/getPodsByDBName.ts @@ -3,6 +3,7 @@ import { ApiResp } from '@/services/kubernet'; import { authSession } from '@/services/backend/auth'; import { getK8s } from '@/services/backend/kubernetes'; import { jsonRes } from '@/services/backend/response'; +import { KBBackupNameLabel } from '@/constants/db'; // get App Metrics By DeployName. compute average value export default async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -26,7 +27,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< undefined, undefined, undefined, - `app.kubernetes.io/instance=${name}` + `app.kubernetes.io/instance=${name},!${KBBackupNameLabel}` ); jsonRes(res, { diff --git a/frontend/providers/dbprovider/src/pages/db/detail/components/AppBaseInfo.tsx b/frontend/providers/dbprovider/src/pages/db/detail/components/AppBaseInfo.tsx index dbac6e0e802..60d7b58b893 100644 --- a/frontend/providers/dbprovider/src/pages/db/detail/components/AppBaseInfo.tsx +++ b/frontend/providers/dbprovider/src/pages/db/detail/components/AppBaseInfo.tsx @@ -151,7 +151,8 @@ const AppBaseInfo = ({ db = defaultDBDetail }: { db: DBDetailType }) => { [DBTypeEnum.kafka]: ``, [DBTypeEnum.qdrant]: ``, [DBTypeEnum.nebula]: ``, - [DBTypeEnum.weaviate]: `` + [DBTypeEnum.weaviate]: ``, + [DBTypeEnum.milvus]: `` }; const defaultCommand = commandMap[db.dbType]; diff --git a/frontend/providers/dbprovider/src/pages/db/detail/components/BackupTable.tsx b/frontend/providers/dbprovider/src/pages/db/detail/components/BackupTable.tsx index c84f509bf94..dfbce7affbf 100644 --- a/frontend/providers/dbprovider/src/pages/db/detail/components/BackupTable.tsx +++ b/frontend/providers/dbprovider/src/pages/db/detail/components/BackupTable.tsx @@ -57,7 +57,7 @@ const BackupTable = ({ db }: { db?: DBDetailType }, ref: ForwardedRef(); + const [backupInfo, setBackupInfo] = useState(); const { isInitialLoading, @@ -160,7 +160,7 @@ const BackupTable = ({ db }: { db?: DBDetailType }, ref: ForwardedRef - setRestoreBackupName(item.name)}> + setBackupInfo(item)}> @@ -250,12 +250,8 @@ const BackupTable = ({ db }: { db?: DBDetailType }, ref: ForwardedRef )} - {!!restoreBackupName && ( - setRestoreBackupName(undefined)} - /> + {!!backupInfo?.name && ( + setBackupInfo(undefined)} /> )} ); diff --git a/frontend/providers/dbprovider/src/pages/db/detail/components/RestoreModal.tsx b/frontend/providers/dbprovider/src/pages/db/detail/components/RestoreModal.tsx index 1064471c33a..3626dac616b 100644 --- a/frontend/providers/dbprovider/src/pages/db/detail/components/RestoreModal.tsx +++ b/frontend/providers/dbprovider/src/pages/db/detail/components/RestoreModal.tsx @@ -20,19 +20,19 @@ import Tip from '@/components/Tip'; import { InfoOutlineIcon } from '@chakra-ui/icons'; import { useTranslation } from 'next-i18next'; import { useForm } from 'react-hook-form'; -import { DBDetailType } from '@/types/db'; +import { BackupItemType, DBDetailType } from '@/types/db'; import { json2CreateCluster, json2Account } from '@/utils/json2Yaml'; import { useRouter } from 'next/router'; import { applyYamlList } from '@/api/db'; const BackupModal = ({ db, - backupName, + backupInfo, onClose, onSuccess }: { db: DBDetailType; - backupName: string; + backupInfo: BackupItemType; onClose: () => void; onSuccess?: () => void; }) => { @@ -53,7 +53,7 @@ const BackupModal = ({ ...db, dbName: databaseName }; - const yamlList = [json2CreateCluster(dbData, backupName), json2Account(dbData)]; + const yamlList = [json2CreateCluster(dbData, backupInfo), json2Account(dbData)]; return applyYamlList(yamlList, 'create'); }, onSuccess() { diff --git a/frontend/providers/dbprovider/src/pages/db/detail/index.tsx b/frontend/providers/dbprovider/src/pages/db/detail/index.tsx index 0d984c514d9..5d15479c3df 100644 --- a/frontend/providers/dbprovider/src/pages/db/detail/index.tsx +++ b/frontend/providers/dbprovider/src/pages/db/detail/index.tsx @@ -156,12 +156,6 @@ const AppDetail = ({ ml={3} variant={'primary'} onClick={() => { - if (dbDetail.dbType === DBTypeEnum.redis) { - return toast({ - status: 'warning', - title: t('Redis does not support backup at this time') - }); - } BackupTableRef.current?.openBackup(); }} > diff --git a/frontend/providers/dbprovider/src/pages/dbs/index.tsx b/frontend/providers/dbprovider/src/pages/dbs/index.tsx index 73a649a0fb3..cc3be741895 100644 --- a/frontend/providers/dbprovider/src/pages/dbs/index.tsx +++ b/frontend/providers/dbprovider/src/pages/dbs/index.tsx @@ -10,6 +10,7 @@ function Home() { const { dbList, setDBList } = useDBStore(); const { Loading } = useLoading(); const [initialized, setInitialized] = useState(false); + const { refetch } = useQuery(['initDbData'], setDBList, { refetchInterval: 3000, onSettled() { diff --git a/frontend/providers/dbprovider/src/store/static.ts b/frontend/providers/dbprovider/src/store/static.ts index c4415c27fc3..af5614034f7 100644 --- a/frontend/providers/dbprovider/src/store/static.ts +++ b/frontend/providers/dbprovider/src/store/static.ts @@ -23,7 +23,8 @@ export let DBVersionMap: DBVersionMapType = { [DBTypeEnum.kafka]: [{ id: 'kafka-3.3.2', label: 'kafka-3.3.2' }], [DBTypeEnum.qdrant]: [{ id: 'qdrant-1.1.0', label: 'qdrant-1.1.0' }], [DBTypeEnum.nebula]: [{ id: 'nebula-v3.5.0', label: 'nebula-v3.5.0' }], - [DBTypeEnum.weaviate]: [{ id: 'weaviate-1.18.0', label: 'weaviate-1.18.0' }] + [DBTypeEnum.weaviate]: [{ id: 'weaviate-1.18.0', label: 'weaviate-1.18.0' }], + [DBTypeEnum.milvus]: [{ id: 'milvus-2.2.4', label: 'milvus-2.2.4' }] }; export const getUserPrice = async () => { diff --git a/frontend/providers/dbprovider/src/types/db.d.ts b/frontend/providers/dbprovider/src/types/db.d.ts index 839eff30934..983cb63ac28 100644 --- a/frontend/providers/dbprovider/src/types/db.d.ts +++ b/frontend/providers/dbprovider/src/types/db.d.ts @@ -114,4 +114,5 @@ export interface BackupItemType { startTime: Date; failureReason?: string; type: `${BackupTypeEnum}`; + connectionPassword: string; } diff --git a/frontend/providers/dbprovider/src/utils/adapt.ts b/frontend/providers/dbprovider/src/utils/adapt.ts index bb94a861b69..daf02402e0b 100644 --- a/frontend/providers/dbprovider/src/utils/adapt.ts +++ b/frontend/providers/dbprovider/src/utils/adapt.ts @@ -29,8 +29,8 @@ export const adaptDBListItem = (db: KbPgClusterType): DBListItemType => { ? dbStatusMap[db?.status?.phase] : dbStatusMap.UnKnow, createTime: dayjs(db.metadata?.creationTimestamp).format('YYYY/MM/DD HH:mm'), - cpu: cpuFormatToM(db.spec?.componentSpecs?.[0]?.resources.limits.cpu), - memory: cpuFormatToM(db.spec?.componentSpecs?.[0]?.resources.limits.memory), + cpu: cpuFormatToM(db.spec?.componentSpecs?.[0]?.resources?.limits?.cpu), + memory: cpuFormatToM(db.spec?.componentSpecs?.[0]?.resources?.limits?.memory), storage: db.spec?.componentSpecs?.[0]?.volumeClaimTemplates?.[0]?.spec?.resources?.requests?.storage || '-', @@ -149,6 +149,8 @@ export const adaptEvents = (events: CoreV1EventList): PodEvent[] => { export const adaptBackup = (backup: BackupCRItemType): BackupItemType => { const autoLabel = 'dataprotection.kubeblocks.io/autobackup'; + const passwordLabel = 'dataprotection.kubeblocks.io/connection-password'; + return { id: backup.metadata.uid, name: backup.metadata.name, @@ -159,7 +161,8 @@ export const adaptBackup = (backup: BackupCRItemType): BackupItemType => { startTime: backup.metadata.creationTimestamp, type: autoLabel in backup.metadata.labels ? BackupTypeEnum.auto : BackupTypeEnum.manual, remark: backup.metadata.labels[BACKUP_REMARK_LABEL_KEY] || '-', - failureReason: backup.status?.failureReason + failureReason: backup.status?.failureReason, + connectionPassword: backup.metadata?.annotations?.[passwordLabel] }; }; diff --git a/frontend/providers/dbprovider/src/utils/json2Yaml.ts b/frontend/providers/dbprovider/src/utils/json2Yaml.ts index 37227418405..805ade2ea91 100644 --- a/frontend/providers/dbprovider/src/utils/json2Yaml.ts +++ b/frontend/providers/dbprovider/src/utils/json2Yaml.ts @@ -8,7 +8,7 @@ import { crLabelKey } from '@/constants/db'; import { StorageClassName } from '@/store/env'; -import type { DBDetailType, DBEditType, DBType } from '@/types/db'; +import type { BackupItemType, DBDetailType, DBEditType, DBType } from '@/types/db'; import { DumpForm, MigrateForm } from '@/types/migrate'; import { formatTime, str2Num } from '@/utils/tools'; import dayjs from 'dayjs'; @@ -16,7 +16,8 @@ import yaml from 'js-yaml'; import { getUserNamespace } from './user'; import { V1StatefulSet } from '@kubernetes/client-node'; -export const json2CreateCluster = (data: DBEditType, backupName?: string) => { +export const json2CreateCluster = (data: DBEditType, backupInfo?: BackupItemType) => { + const userNS = getUserNamespace(); const resources = { limits: { cpu: `${str2Num(Math.floor(data.cpu))}m`, @@ -27,6 +28,7 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { memory: `${Math.floor(str2Num(data.memory) * 0.1)}Mi` } }; + const terminationPolicy = backupInfo?.name ? 'WipeOut' : 'Delete'; const metadata = { finalizers: ['cluster.kubeblocks.io/finalizer'], labels: { @@ -35,10 +37,21 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { [crLabelKey]: data.dbName }, annotations: { - ...(backupName ? { [BACKUP_LABEL_KEY]: JSON.stringify({ [data.dbType]: backupName }) } : {}) + ...(backupInfo?.name + ? { + [BACKUP_LABEL_KEY]: JSON.stringify({ + [data.dbType === 'apecloud-mysql' ? 'mysql' : data.dbType]: { + name: backupInfo.name, + namespace: userNS, + connectionPassword: backupInfo.connectionPassword + } + }) + } + : {}) }, name: data.dbName }; + const storageClassName = StorageClassName ? { storageClassName: StorageClassName } : {}; const redisHA = RedisHAConfig(data.replicas > 1); @@ -85,7 +98,7 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { ] } ], - terminationPolicy: 'Delete', + terminationPolicy, tolerations: [] } } @@ -128,7 +141,7 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { ] } ], - terminationPolicy: 'Delete', + terminationPolicy, tolerations: [] } } @@ -174,7 +187,7 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { ] } ], - terminationPolicy: 'Delete', + terminationPolicy, tolerations: [] } } @@ -255,7 +268,7 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { : {}) } ], - terminationPolicy: 'Delete', + terminationPolicy, tolerations: [] } } @@ -364,7 +377,7 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { ] } ], - terminationPolicy: 'Delete', + terminationPolicy, tolerations: [] } } @@ -406,7 +419,7 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { ] } ], - terminationPolicy: 'Delete', + terminationPolicy, tolerations: [] } } @@ -511,7 +524,7 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { ] } ], - terminationPolicy: 'Delete', + terminationPolicy, tolerations: [] } } @@ -553,12 +566,101 @@ export const json2CreateCluster = (data: DBEditType, backupName?: string) => { ] } ], - terminationPolicy: 'Delete', + terminationPolicy, + tolerations: [] + } + } + ], + [DBTypeEnum.milvus]: [ + { + apiVersion: 'apps.kubeblocks.io/v1alpha1', + kind: 'Cluster', + metadata, + spec: { + affinity: { + podAntiAffinity: 'Preferred', + tenancy: 'SharedNode' + }, + clusterDefinitionRef: 'milvus', + clusterVersionRef: data.dbVersion, + componentSpecs: [ + { + componentDefRef: 'milvus', + monitor: false, + name: 'milvus', + noCreatePDB: false, + replicas: data.replicas, + resources, + rsmTransformPolicy: 'ToSts', + serviceAccountName: data.dbName, + volumeClaimTemplates: [ + { + name: 'data', + spec: { + accessModes: ['ReadWriteOnce'], + resources: { + requests: { + storage: `${data.storage}Gi` + } + } + } + } + ] + }, + { + componentDefRef: 'etcd', + monitor: false, + name: 'etcd', + noCreatePDB: false, + replicas: data.replicas, + resources, + rsmTransformPolicy: 'ToSts', + serviceAccountName: data.dbName, + volumeClaimTemplates: [ + { + name: 'data', + spec: { + accessModes: ['ReadWriteOnce'], + resources: { + requests: { + storage: `${data.storage}Gi` + } + } + } + } + ] + }, + { + componentDefRef: 'minio', + monitor: false, + name: 'minio', + noCreatePDB: false, + replicas: data.replicas, + resources, + rsmTransformPolicy: 'ToSts', + serviceAccountName: data.dbName, + volumeClaimTemplates: [ + { + name: 'data', + spec: { + accessModes: ['ReadWriteOnce'], + resources: { + requests: { + storage: `${data.storage}Gi` + } + } + } + } + ] + } + ], + terminationPolicy, tolerations: [] } } ] }; + console.log(map[data.dbType].map((item) => yaml.dump(item)).join('\n---\n')); return map[data.dbType].map((item) => yaml.dump(item)).join('\n---\n'); }; @@ -615,32 +717,47 @@ export const json2Account = (data: DBEditType) => { ] }; + const baseRoleRules = [ + { + apiGroups: [''], + resources: ['events'], + verbs: ['create'] + }, + { + apiGroups: [''], + resources: ['configmaps'], + verbs: ['create', 'get', 'list', 'patch', 'update', 'watch', 'delete'] + }, + { + apiGroups: [''], + resources: ['endpoints'], + verbs: ['create', 'get', 'list', 'patch', 'update', 'watch', 'delete'] + }, + { + apiGroups: [''], + resources: ['pods'], + verbs: ['get', 'list', 'patch', 'update', 'watch'] + } + ]; + + const BackupRoleRules = [ + { + apiGroups: ['dataprotection.kubeblocks.io'], + resources: ['backups'], + verbs: ['create', 'get', 'list', 'patch', 'update', 'watch', 'delete'] + }, + { + apiGroups: ['dataprotection.kubeblocks.io'], + resources: ['backups/status'], + verbs: ['create', 'get', 'list', 'patch', 'update', 'watch', 'delete'] + } + ]; + const pgAccountTemplate = [ commonBase, { ...dbRolesBase, - rules: [ - { - apiGroups: [''], - resources: ['events'], - verbs: ['create'] - }, - { - apiGroups: [''], - resources: ['configmaps'], - verbs: ['create', 'get', 'list', 'patch', 'update', 'watch', 'delete'] - }, - { - apiGroups: [''], - resources: ['endpoints'], - verbs: ['create', 'get', 'list', 'patch', 'update', 'watch', 'delete'] - }, - { - apiGroups: [''], - resources: ['pods'], - verbs: ['get', 'list', 'patch', 'update', 'watch'] - } - ] + rules: [...baseRoleRules, ...BackupRoleRules] }, dbRoleBindingBase ]; @@ -656,7 +773,8 @@ export const json2Account = (data: DBEditType) => { apiGroups: [''], resources: ['events'], verbs: ['create'] - } + }, + ...BackupRoleRules ] }, dbRoleBindingBase @@ -667,10 +785,17 @@ export const json2Account = (data: DBEditType) => { ...dbRolesBase, rules: [ { - apiGroups: [''], - resources: ['events'], - verbs: ['create'] - } + apiGroups: ['apps.kubeblocks.io'], + resources: ['clusters'], + verbs: ['get', 'list'] + }, + { + apiGroups: ['apps.kubeblocks.io'], + resources: ['clusters/status'], + verbs: ['get'] + }, + ...baseRoleRules, + ...BackupRoleRules ] }, dbRoleBindingBase @@ -684,7 +809,8 @@ export const json2Account = (data: DBEditType) => { apiGroups: [''], resources: ['events'], verbs: ['create'] - } + }, + ...BackupRoleRules ] }, dbRoleBindingBase @@ -692,7 +818,8 @@ export const json2Account = (data: DBEditType) => { [DBTypeEnum.kafka]: pgAccountTemplate, [DBTypeEnum.qdrant]: pgAccountTemplate, [DBTypeEnum.nebula]: pgAccountTemplate, - [DBTypeEnum.weaviate]: pgAccountTemplate + [DBTypeEnum.weaviate]: pgAccountTemplate, + [DBTypeEnum.milvus]: pgAccountTemplate }; return map[data.dbType].map((item) => yaml.dump(item)).join('\n---\n'); }; @@ -792,8 +919,10 @@ export const json2Restart = ({ dbName, dbType }: { dbName: string; dbType: DBTyp export const json2ManualBackup = ({ name, backupPolicyName, - remark = '' + backupMethod, + remark }: { + backupMethod: string; name: string; backupPolicyName: string; remark?: string; @@ -802,7 +931,7 @@ export const json2ManualBackup = ({ apiVersion: 'dataprotection.kubeblocks.io/v1alpha1', kind: 'Backup', metadata: { - finalizers: ['dataprotection.kubeblocks.io/finalizer'], + // finalizers: ['dataprotection.kubeblocks.io/finalizer'], labels: { [BACKUP_REMARK_LABEL_KEY]: remark }, @@ -810,7 +939,8 @@ export const json2ManualBackup = ({ }, spec: { backupPolicyName, - backupType: 'datafile' + // backupType: 'datafile' + backupMethod } }; return yaml.dump(template); @@ -842,7 +972,8 @@ export const json2MigrateCR = (data: MigrateForm) => { kafka: '', qdrant: '', nebula: '', - weaviate: '' + weaviate: '', + milvus: '' }; const template = { @@ -931,7 +1062,8 @@ export const json2NetworkService = ({ kafka: '', qdrant: '', nebula: '', - weaviate: '' + weaviate: '', + milvus: '' }; const template = { diff --git a/frontend/providers/dbprovider/src/utils/user.ts b/frontend/providers/dbprovider/src/utils/user.ts index 0d25ebf06fc..5aaf52c9f98 100644 --- a/frontend/providers/dbprovider/src/utils/user.ts +++ b/frontend/providers/dbprovider/src/utils/user.ts @@ -18,7 +18,7 @@ export const getUserNamespace = () => { const kubeConfig = getUserKubeConfig(); const json: any = yaml.load(kubeConfig); try { - return `ns-${json.users[0].name}`; + return json?.contexts[0]?.context?.namespace || `ns-${json.users[0].name}`; } catch (err) { return 'ns-'; }