Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: optimize database pause and backup handling #5242

Merged
merged 7 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions frontend/providers/applaunchpad/src/api/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
adaptMetrics,
adaptEvents
} from '@/utils/adapt';
import type { AppPatchPropsType } from '@/types/app';
import type { AppPatchPropsType, PodDetailType } from '@/types/app';
import { MonitorDataResult, MonitorQueryKey } from '@/types/monitor';

export const postDeployApp = (yamlList: string[]) => POST('/api/applyApp', { yamlList });
Expand All @@ -27,7 +27,7 @@ export const getAppByName = (name: string) =>
GET(`/api/getAppByAppName?appName=${name}`).then(adaptAppDetail);

export const getAppPodsByAppName = (name: string) =>
GET<V1Pod[]>('/api/getAppPodsByAppName', { name }).then((item) => item.map(adaptPod));
GET<PodDetailType[]>('/api/getAppPodsByAppName', { name });

export const getPodsMetrics = (podsName: string[]) =>
POST<SinglePodMetrics[]>('/api/getPodsMetrics', { podsName }).then((item) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 { adaptPod } from '@/utils/adapt';

// get App Metrics By DeployName. compute average value
export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
Expand Down Expand Up @@ -30,7 +31,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
);

jsonRes(res, {
data: pods
data: pods.map((item) => adaptPod(item))
});
} catch (err: any) {
// console.log(err, 'get metrics error')
Expand Down
5 changes: 2 additions & 3 deletions frontend/providers/applaunchpad/src/pages/app/edit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,7 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) =>
t,
applySuccess,
userSourcePrice?.gpu,
refetchPrice,
isGuided
refetchPrice
]
);

Expand Down Expand Up @@ -322,7 +321,7 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) =>
formHook.setValue('networks', completeNetworks);
}
} catch (error) {}
}, []);
}, [router.query]);

return (
<>
Expand Down
5 changes: 3 additions & 2 deletions frontend/providers/dbprovider/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"backup_database": "Backup Database",
"backup_deleting": "Purging Backup",
"backup_failed": "Backup Failed",
"backup_list": "Backup History",
"backup_list": "Data Backups",
"backup_name": "Backup Name",
"backup_name_cannot_empty": "Must provide backup name",
"backup_processing": "Saving Backup",
Expand Down Expand Up @@ -316,5 +316,6 @@
"within_1_hour": "Within 1 hour",
"within_5_minutes": "Within 5 minutes",
"yaml_file": "YAML",
"you_have_successfully_deployed_database": "You have successfully deployed and created a database!"
"you_have_successfully_deployed_database": "You have successfully deployed and created a database!",
"database_name_max_length": "Database name length cannot exceed {{length}} characters"
}
7 changes: 4 additions & 3 deletions frontend/providers/dbprovider/public/locales/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"backup_database": "备份数据库",
"backup_deleting": "删除中",
"backup_failed": "备份失败",
"backup_list": "备份历史",
"backup_list": "数据备份",
"backup_name": "备份名",
"backup_name_cannot_empty": "备份名称不能为空",
"backup_processing": "备份中",
Expand Down Expand Up @@ -316,5 +316,6 @@
"within_1_hour": "一小时内",
"within_5_minutes": "五分钟内",
"yaml_file": "YAML 文件",
"you_have_successfully_deployed_database": "您已成功部署创建一个数据库!"
}
"you_have_successfully_deployed_database": "您已成功部署创建一个数据库!",
"database_name_max_length": "数据库名长度不能超过 {{length}} 个字符"
}
2 changes: 1 addition & 1 deletion frontend/providers/dbprovider/src/api/backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { Props as UpdatePolicyProps } from '@/pages/api/backup/updatePolicy
* for the specific database in the cluster.
*
* To update the auto-backup policy, use the PATCH operation on the 'cluster spec backup' resource.
*
* @deprecated
* @param data - Object containing information about the database, including dbName and dbType.
* @returns {Promise<AutoBackupFormType>} - A promise resolving to the auto-backup configuration form.
*/
Expand Down
20 changes: 5 additions & 15 deletions frontend/providers/dbprovider/src/api/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const applyYamlList = (yamlList: string[], type: 'create' | 'replace' | '
POST('/api/applyYamlList', { yamlList, type });

export const getPodsByDBName = (name: string): Promise<PodDetailType[]> =>
GET('/api/pod/getPodsByDBName', { name }).then((res) => res.map(adaptPod));
GET('/api/pod/getPodsByDBName', { name });

export const getPodLogs = (data: {
dbName: string;
Expand All @@ -66,21 +66,11 @@ export const restartDB = (data: { dbName: string; dbType: DBType }) => {
return applyYamlList([yaml], 'update');
};

export const pauseDBByName = (data: { dbName: string; dbType: DBType }) => {
const yaml = json2StartOrStop({
...data,
type: 'Stop'
});
return applyYamlList([yaml], 'update');
};
export const pauseDBByName = (data: { dbName: string; dbType: DBType }) =>
POST('/api/pauseDBByName', data);

export const startDBByName = (data: { dbName: string; dbType: DBType }) => {
const yaml = json2StartOrStop({
...data,
type: 'Start'
});
return applyYamlList([yaml], 'update');
};
export const startDBByName = (data: { dbName: string; dbType: DBType }) =>
POST('/api/startDBByName', data);

export const getDBServiceByName = (name: string) =>
GET<V1Service>(`/api/getServiceByName?name=${name}`);
Expand Down
61 changes: 58 additions & 3 deletions frontend/providers/dbprovider/src/pages/api/createDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { KbPgClusterType } from '@/types/cluster';
import { BackupItemType, DBEditType } from '@/types/db';
import { json2Account, json2CreateCluster } from '@/utils/json2Yaml';
import { json2Account, json2ClusterOps, json2CreateCluster } from '@/utils/json2Yaml';
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
Expand All @@ -20,8 +20,63 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
});

if (isEdit) {
const cluster = json2CreateCluster(dbForm);
await applyYamlList([cluster], 'replace');
const { body } = (await k8sCustomObjects.getNamespacedCustomObject(
'apps.kubeblocks.io',
'v1alpha1',
namespace,
'clusters',
dbForm.dbName
)) as {
body: KbPgClusterType;
};

const currentConfig = {
cpu: parseInt(body.spec.componentSpecs[0].resources.limits.cpu.replace('m', '')),
memory: parseInt(body.spec.componentSpecs[0].resources.limits.memory.replace('Mi', '')),
replicas: body.spec.componentSpecs[0].replicas,
storage: parseInt(
body.spec.componentSpecs[0].volumeClaimTemplates[0].spec.resources.requests.storage.replace(
'Gi',
''
)
)
};

const opsRequests = [];

if (currentConfig.cpu !== dbForm.cpu || currentConfig.memory !== dbForm.memory) {
const verticalScalingYaml = json2ClusterOps(dbForm, 'VerticalScaling');
opsRequests.push(verticalScalingYaml);
}

if (currentConfig.replicas !== dbForm.replicas) {
const horizontalScalingYaml = json2ClusterOps(dbForm, 'HorizontalScaling');
opsRequests.push(horizontalScalingYaml);
}

if (dbForm.storage > currentConfig.storage) {
const volumeExpansionYaml = json2ClusterOps(dbForm, 'VolumeExpansion');
opsRequests.push(volumeExpansionYaml);
}

console.log('DB Edit Operation:', {
dbName: dbForm.dbName,
changes: {
cpu: currentConfig.cpu !== dbForm.cpu,
memory: currentConfig.memory !== dbForm.memory,
replicas: currentConfig.replicas !== dbForm.replicas,
storage: dbForm.storage > currentConfig.storage
},
opsCount: opsRequests.length
});

if (opsRequests.length > 0) {
await applyYamlList(opsRequests, 'create');
return jsonRes(res, {
data: `Successfully submitted ${opsRequests.length} change requests`
});
}

return jsonRes(res, {
data: 'success update db'
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
key: 'redis'
},
[DBTypeEnum.kafka]: {
key: 'kafka'
key: 'kafka-broker'
},
[DBTypeEnum.qdrant]: {
key: 'qdrant'
Expand Down
73 changes: 73 additions & 0 deletions frontend/providers/dbprovider/src/pages/api/pauseDBByName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { authSession } from '@/services/backend/auth';
import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { KbPgClusterType } from '@/types/cluster';
import { json2StartOrStop } from '@/utils/json2Yaml';
import { PatchUtils } from '@kubernetes/client-node';
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const { dbName } = req.body as {
dbName: string;
};

if (!dbName) {
return jsonRes(res, {
code: 400,
error: 'params error'
});
}

const { applyYamlList, k8sCustomObjects, namespace } = await getK8s({
kubeconfig: await authSession(req)
});

const { yaml, yamlObj } = json2StartOrStop({
dbName,
type: 'Stop'
});

const { body } = (await k8sCustomObjects.getNamespacedCustomObject(
'apps.kubeblocks.io',
'v1alpha1',
namespace,
'clusters',
dbName
)) as {
body: KbPgClusterType;
};

if (body.spec.backup?.enabled === true) {
const patch = [
{
op: 'replace',
path: '/spec/backup/enabled',
value: false
}
];
await k8sCustomObjects.patchNamespacedCustomObject(
'apps.kubeblocks.io',
'v1alpha1',
namespace,
'clusters',
dbName,
patch,
undefined,
undefined,
undefined,
{ headers: { 'Content-type': PatchUtils.PATCH_FORMAT_JSON_PATCH } }
);
}

await applyYamlList([yaml], 'update');

jsonRes(res, { data: 'pause success' });
} catch (err: any) {
jsonRes(res, {
code: 500,
error: err
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { authSession } from '@/services/backend/auth';
import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { KBBackupNameLabel } from '@/constants/db';
import { adaptPod } from '@/utils/adapt';

// get App Metrics By DeployName. compute average value
export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
Expand Down Expand Up @@ -31,7 +32,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
);

jsonRes(res, {
data: pods
data: pods.map((pod) => adaptPod(pod))
});
} catch (err: any) {
// console.log(err, 'get metrics error')
Expand Down
75 changes: 75 additions & 0 deletions frontend/providers/dbprovider/src/pages/api/startDBByName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { authSession } from '@/services/backend/auth';
import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { KbPgClusterType } from '@/types/cluster';
import { json2StartOrStop } from '@/utils/json2Yaml';
import { PatchUtils } from '@kubernetes/client-node';
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const { dbName } = req.body as {
dbName: string;
};

if (!dbName) {
return jsonRes(res, {
code: 400,
error: 'params error'
});
}

const { applyYamlList, k8sCustomObjects, namespace } = await getK8s({
kubeconfig: await authSession(req)
});

const { yaml, yamlObj } = json2StartOrStop({
dbName,
type: 'Start'
});

const { body } = (await k8sCustomObjects.getNamespacedCustomObject(
'apps.kubeblocks.io',
'v1alpha1',
namespace,
'clusters',
dbName
)) as {
body: KbPgClusterType;
};

console.log(yamlObj, body.spec.backup, body.spec.backup?.enabled === false, 'yaml');

if (body.spec.backup?.enabled === false) {
const patch = [
{
op: 'replace',
path: '/spec/backup/enabled',
value: true
}
];

await k8sCustomObjects.patchNamespacedCustomObject(
'apps.kubeblocks.io',
'v1alpha1',
namespace,
'clusters',
dbName,
patch,
undefined,
undefined,
undefined,
{ headers: { 'Content-type': PatchUtils.PATCH_FORMAT_JSON_PATCH } }
);
}
await applyYamlList([yaml], 'update');

jsonRes(res, { data: 'start success' });
} catch (err: any) {
jsonRes(res, {
code: 500,
error: err
});
}
}
Loading
Loading