Skip to content

Commit

Permalink
fix:launchpad issuer and certificates (#4405)
Browse files Browse the repository at this point in the history
* fix:launchpad issuer and certificates

Signed-off-by: jingyang <3161362058@qq.com>

* fix text

Signed-off-by: jingyang <3161362058@qq.com>

---------

Signed-off-by: jingyang <3161362058@qq.com>
  • Loading branch information
zjy365 authored Dec 13, 2023
1 parent a3efc3a commit 4c166d3
Show file tree
Hide file tree
Showing 13 changed files with 232 additions and 229 deletions.
8 changes: 6 additions & 2 deletions frontend/providers/applaunchpad/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,5 +178,9 @@
"let me think again": "let me think again",
"Configurable number of instances or automatic horizontal scaling": "Configurable number of instances or automatic horizontal scaling",
"gift time tip": "Within {{time}} hours ",
"gift amount tip": "Recharge {{amount}} and get {{gift}} free"
}
"gift amount tip": "Recharge {{amount}} and get {{gift}} free",
"Add Port": "Add Port",
"Age": "Age",
"Amount": "Amount",
"ConfigMap Tip": "ConfigMap"
}
5 changes: 3 additions & 2 deletions frontend/providers/applaunchpad/public/locales/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,5 +220,6 @@
"let me think again": "我再想想",
"Configurable number of instances or automatic horizontal scaling": "可配置实例数或自动横向伸缩",
"gift time tip": "{{time}} 小时内",
"gift amount tip": "充值 {{amount}} 赠送 {{gift}} "
}
"gift amount tip": "充值 {{amount}} 赠送 {{gift}} ",
"ConfigMap Tip": "配置文件"
}
74 changes: 56 additions & 18 deletions frontend/providers/applaunchpad/src/pages/api/delApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,65 @@ export async function DeleteAppByName({ name, req }: DeleteAppParams & { req: Ne
kubeconfig: await authSession(req.headers)
});

// delete Certificate
const certificatesList = (await k8sCustomObjects.listNamespacedCustomObject(
'cert-manager.io',
'v1',
namespace,
'certificates',
undefined,
undefined,
undefined,
undefined,
`${appDeployKey}=${name}`
)) as { body: { items: any[] } };
const delCertList = certificatesList.body.items.map((item) =>
k8sCustomObjects.deleteNamespacedCustomObject(
'cert-manager.io',
'v1',
namespace,
'certificates',
item.metadata.name
)
);

// delete Issuer
const issuersList = (await k8sCustomObjects.listNamespacedCustomObject(
'cert-manager.io',
'v1',
namespace,
'issuers',
undefined,
undefined,
undefined,
undefined,
`${appDeployKey}=${name}`
)) as { body: { items: any[] } };
const delIssuerList = issuersList.body.items.map(async (item) =>
k8sCustomObjects.deleteNamespacedCustomObject(
'cert-manager.io',
'v1',
namespace,
'issuers',
item.metadata.name
)
);

const delIssuerAndCert = await Promise.allSettled([...delCertList, ...delIssuerList]);
/* find not 404 error */
delIssuerAndCert.forEach((item) => {
console.log(item, 'delIssuerAndCert err');
if (item.status === 'rejected' && +item?.reason?.body?.code !== 404) {
throw new Error(item?.reason?.body?.message || item?.reason?.body?.reason || '删除 App 异常');
}
});

/* delete all sources */
const delDependent = await Promise.allSettled([
k8sCore.deleteNamespacedService(name, namespace), // delete service
k8sCore.deleteNamespacedConfigMap(name, namespace), // delete configMap
k8sCore.deleteNamespacedSecret(name, namespace), // delete secret
// delete Ingress
k8sNetworkingApp.deleteCollectionNamespacedIngress(
namespace,
undefined,
Expand All @@ -46,25 +100,9 @@ export async function DeleteAppByName({ name, req }: DeleteAppParams & { req: Ne
undefined,
undefined,
`${appDeployKey}=${name}`
), // delete Ingress
k8sCustomObjects.deleteNamespacedCustomObject(
// delete Issuer
'cert-manager.io',
'v1',
namespace,
'issuers',
name
),
k8sCustomObjects.deleteNamespacedCustomObject(
// delete Certificate
'cert-manager.io',
'v1',
namespace,
'certificates',
name
),
// delete pvc
k8sCore.deleteCollectionNamespacedPersistentVolumeClaim(
// delete pvc
namespace,
undefined,
undefined,
Expand Down Expand Up @@ -92,7 +130,7 @@ export async function DeleteAppByName({ name, req }: DeleteAppParams & { req: Ne

/* find not 404 error */
delApp.forEach((item) => {
console.log(item, 'delApp err');
console.log(item, 'delApp Deployment StatefulSet err');
if (item.status === 'rejected' && +item?.reason?.body?.code !== 404) {
throw new Error(item?.reason?.body?.reason || item?.reason?.body?.message || '删除 App 异常');
}
Expand Down
22 changes: 14 additions & 8 deletions frontend/providers/applaunchpad/src/pages/api/updateApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,22 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
delete: (name) => k8sNetworkingApp.deleteNamespacedIngress(name, namespace)
},
[YamlKindEnum.Issuer]: {
patch: (jsonPatch: Object) =>
k8sCustomObjects.patchNamespacedCustomObject(
patch: (jsonPatch: Object) => {
// @ts-ignore
const name = jsonPatch?.metadata?.name;
return k8sCustomObjects.patchNamespacedCustomObject(
'cert-manager.io',
'v1',
namespace,
'issuers',
appName,
name,
jsonPatch,
undefined,
undefined,
undefined,
{ headers: { 'Content-type': PatchUtils.PATCH_FORMAT_JSON_MERGE_PATCH } }
),
);
},
delete: (name) =>
k8sCustomObjects.deleteNamespacedCustomObject(
'cert-manager.io',
Expand All @@ -133,19 +136,22 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
)
},
[YamlKindEnum.Certificate]: {
patch: (jsonPatch: Object) =>
k8sCustomObjects.patchNamespacedCustomObject(
patch: (jsonPatch: Object) => {
// @ts-ignore
const name = jsonPatch?.metadata?.name;
return k8sCustomObjects.patchNamespacedCustomObject(
'cert-manager.io',
'v1',
namespace,
'certificates',
appName,
name,
jsonPatch,
undefined,
undefined,
undefined,
{ headers: { 'Content-type': PatchUtils.PATCH_FORMAT_JSON_MERGE_PATCH } }
),
);
},
delete: (name) =>
k8sCustomObjects.deleteNamespacedCustomObject(
'cert-manager.io',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ const ConfigmapModal = ({
<Modal isOpen onClose={closeCb}>
<ModalOverlay />
<ModalContent maxH={'90vh'} maxW={'90vw'} minW={'600px'} w={'auto'}>
<ModalHeader>{t(textMap[type].title)} ConfigMap</ModalHeader>
<ModalHeader>
{t(textMap[type].title)}
{t('ConfigMap Tip')}
</ModalHeader>
<ModalCloseButton />
<ModalBody>
<MyFormControl showError errorText={errors.mountPath?.message}>
Expand Down
33 changes: 10 additions & 23 deletions frontend/providers/applaunchpad/src/pages/app/edit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ import Yaml from './components/Yaml';
const ErrorModal = dynamic(() => import('./components/ErrorModal'));

export const formData2Yamls = (
data: AppEditType,
handleType: 'edit' | 'create' = 'create',
crYamlList?: DeployKindsType[]
data: AppEditType
// handleType: 'edit' | 'create' = 'create',
// crYamlList?: DeployKindsType[]
) => [
{
filename: 'service.yaml',
Expand All @@ -47,11 +47,11 @@ export const formData2Yamls = (
!!data.storeList?.length
? {
filename: 'statefulSet.yaml',
value: json2DeployCr(data, 'statefulset', handleType, crYamlList)
value: json2DeployCr(data, 'statefulset')
}
: {
filename: 'deployment.yaml',
value: json2DeployCr(data, 'deployment', handleType, crYamlList)
value: json2DeployCr(data, 'deployment')
},
...(data.configMapList.length > 0
? [
Expand Down Expand Up @@ -257,12 +257,9 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) =>
{
onSuccess(res) {
if (!res) return;
console.log(res, 'init res');
oldAppEditData.current = res;
formOldYamls.current = formData2Yamls(
res,
appName !== '' ? 'edit' : 'create',
res.crYamlList
);
formOldYamls.current = formData2Yamls(res);
crOldYamls.current = res.crYamlList;

setDefaultStorePathList(res.storeList.map((item) => item.path));
Expand All @@ -285,16 +282,10 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) =>
useEffect(() => {
if (tabType === 'yaml') {
try {
setYamlList(
formData2Yamls(
realTimeForm.current,
appName !== '' ? 'edit' : 'create',
crOldYamls.current
)
);
setYamlList(formData2Yamls(realTimeForm.current));
} catch (error) {}
}
}, [appName, router.query.name, tabType]);
}, [router.query.name, tabType]);

return (
<>
Expand All @@ -313,11 +304,7 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) =>
applyCb={() => {
closeGuide();
formHook.handleSubmit((data) => {
const parseYamls = formData2Yamls(
data,
appName !== '' ? 'edit' : 'create',
crOldYamls.current
);
const parseYamls = formData2Yamls(data);
setYamlList(parseYamls);
// balance check
if (balance <= 0) {
Expand Down
4 changes: 2 additions & 2 deletions frontend/providers/applaunchpad/src/types/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ export interface AppEditType {
port: number;
protocol: 'HTTP' | 'GRPC' | 'WS';
openPublicDomain: boolean;
publicDomain: string;
customDomain: string;
publicDomain: string; // default domain
customDomain: string; // custom domain
}[];
envs: {
key: string;
Expand Down
94 changes: 2 additions & 92 deletions frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@ import {
import dayjs from 'dayjs';
import jsonpatch, { Operation } from 'fast-json-patch';

export const json2DeployCr = (
data: AppEditType,
type: 'deployment' | 'statefulset',
handleType: 'edit' | 'create' = 'create',
crYamlList?: DeployKindsType[]
) => {
export const json2DeployCr = (data: AppEditType, type: 'deployment' | 'statefulset') => {
const totalStorage = data.storeList.reduce((acc, item) => acc + item.value, 0);

const metadata = {
Expand Down Expand Up @@ -220,91 +215,6 @@ export const json2DeployCr = (
}
};

const differentJsonPatch = jsonpatch.compare(template['deployment'], template['statefulset']);

// JSON Patch
const patch: Operation[] = [
{ op: 'add', path: '/metadata', value: metadata },
{ op: 'replace', path: '/spec/replicas', value: commonSpec.replicas },
{ op: 'replace', path: '/spec/revisionHistoryLimit', value: commonSpec.revisionHistoryLimit },
{ op: 'replace', path: '/spec/selector', value: commonSpec.selector },
{ op: 'replace', path: '/spec/template/metadata/labels', value: templateMetadata.labels },
{
op: 'replace',
path: '/spec/template/spec/containers/0',
value: {
...commonContainer,
volumeMounts: [...configMapVolumeMounts]
}
},
{
op: 'replace',
path: '/spec/template/spec/volumes',
value: [...configMapVolumes]
},
// gpu
{
op: 'replace',
path: '/spec/template/spec/restartPolicy',
value: gpuMap.restartPolicy
},
{
op: 'replace',
path: '/spec/template/spec/runtimeClassName',
value: gpuMap.runtimeClassName
},
{
op: 'replace',
path: '/spec/template/spec/nodeSelector',
value: gpuMap.nodeSelector
},
// status
{
op: 'remove',
path: '/status'
}
];

const statefulsetPatch: Operation[] = [
{
op: 'replace',
path: '/spec/template/spec/containers/0',
value: {
...commonContainer,
volumeMounts: [
...configMapVolumeMounts,
...data.storeList.map((item) => ({
name: item.name,
mountPath: item.path
}))
]
}
}
];

if (handleType === 'edit' && crYamlList) {
if (type === 'deployment') {
const originYaml = crYamlList.find((i) => i.kind === 'Deployment');
const cloneYaml = jsonpatch.deepClone(originYaml);
const updated = jsonpatch.applyPatch(cloneYaml, patch);
return yaml.dump(updated.newDocument);
} else {
let originStatefulSetYaml = crYamlList.find((i) => i.kind === 'StatefulSet');
const deploymentYaml = crYamlList.find((i) => i.kind === 'Deployment');

// handle deployment to StatefulSet
if (!originStatefulSetYaml && deploymentYaml?.metadata?.name) {
originStatefulSetYaml = jsonpatch.applyPatch(
jsonpatch.deepClone(deploymentYaml),
differentJsonPatch
).newDocument;
}

const cloneYaml = jsonpatch.deepClone(originStatefulSetYaml);
const updated = jsonpatch.applyPatch(cloneYaml, patch.concat(statefulsetPatch));
return yaml.dump(updated.newDocument);
}
}
return yaml.dump(template[type]);
};

Expand Down Expand Up @@ -363,7 +273,7 @@ export const json2Ingress = (data: AppEditType) => {
? network.customDomain
: `${network.publicDomain}.${SEALOS_DOMAIN}`;

const secretName = network.customDomain ? data.appName : INGRESS_SECRET;
const secretName = network.customDomain ? network.networkName : INGRESS_SECRET;

const ingress = {
apiVersion: 'networking.k8s.io/v1',
Expand Down
Loading

0 comments on commit 4c166d3

Please sign in to comment.