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: template other resource #4098

Merged
merged 2 commits into from
Oct 16, 2023
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
2 changes: 1 addition & 1 deletion frontend/desktop/next-i18next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en', 'zh', 'zh-Hans'],
locales: ['en', 'zh'],
localeDetection: false
}
};
3 changes: 2 additions & 1 deletion frontend/desktop/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ export default function Home({
}

export async function getServerSideProps({ req, res, locales }: any) {
const local = req?.cookies?.NEXT_LOCALE || 'en';
const lang: string = req?.headers?.['accept-language'] || 'zh';
const local = lang.indexOf('zh') !== -1 ? 'zh' : 'en';
const sealos_cloud_domain = process.env.SEALOS_CLOUD_DOMAIN || 'cloud.sealos.io';

return {
Expand Down
3 changes: 2 additions & 1 deletion frontend/desktop/src/pages/signin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ export default function SigninPage() {
}

export async function getServerSideProps({ req, res, locales }: any) {
const local = req?.cookies?.NEXT_LOCALE || 'en';
const lang: string = req?.headers?.['accept-language'] || 'zh';
const local = lang.indexOf('zh') !== -1 ? 'zh' : 'en';

const props = {
...(await serverSideTranslations(local, undefined, null, locales || []))
Expand Down
49 changes: 29 additions & 20 deletions frontend/providers/template/src/api/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,39 @@ export const delInstanceByName = (instanceName: string) =>
export const delJobByName = (instanceName: string) =>
DELETE('/api/resource/delJob', { instanceName });

export const deleteResourceByKind = (instanceName: string, kind: ResourceKindType) => {
switch (kind) {
case 'CronJob':
return delCronJobByName(instanceName);
case 'App':
return deleteAppCRD(instanceName);
case 'Secret':
return deleteSecret(instanceName);
case 'AppLaunchpad':
return delApplaunchpad(instanceName);
case 'DataBase':
return delDBByName(instanceName);
case 'Instance':
return delInstanceByName(instanceName);
case 'Job':
return delJobByName(instanceName);
default:
throw new Error(`Unsupported kind: ${kind}`);
}
export const delConfigMapByName = (instanceName: string) =>
DELETE('/api/resource/delConfigMap', { instanceName });

export const delIssuerByName = (instanceName: string) =>
DELETE('/api/resource/deleteIssuer', { instanceName });

export const delRoleByName = (instanceName: string) =>
DELETE('/api/resource/delRole', { instanceName });

export const delRoleBindingByName = (instanceName: string) =>
DELETE('/api/resource/delRoleBinding', { instanceName });

export const delServiceAccountByName = (instanceName: string) =>
DELETE('/api/resource/delServiceAccount', { instanceName });

const deleteResourceByKind: Record<ResourceKindType, (instanceName: string) => void> = {
CronJob: (instanceName: string) => delCronJobByName(instanceName),
App: (instanceName: string) => deleteAppCRD(instanceName),
Secret: (instanceName: string) => deleteSecret(instanceName),
AppLaunchpad: (instanceName: string) => delApplaunchpad(instanceName),
DataBase: (instanceName: string) => delDBByName(instanceName),
Instance: (instanceName: string) => delInstanceByName(instanceName),
Job: (instanceName: string) => delJobByName(instanceName),
ConfigMap: (instanceName: string) => delConfigMapByName(instanceName),
Issuer: (instanceName: string) => delIssuerByName(instanceName),
Role: (instanceName: string) => delRoleByName(instanceName),
RoleBinding: (instanceName: string) => delRoleBindingByName(instanceName),
ServiceAccount: (instanceName: string) => delServiceAccountByName(instanceName)
};

export const deleteAllResources = async (resources: BaseResourceType[]) => {
const deletePromises = resources.map((resource) => {
return deleteResourceByKind(resource.name, resource.kind);
return deleteResourceByKind[resource.kind](resource.name);
});
const reuslt = await Promise.allSettled(deletePromises);
console.log(reuslt);
Expand Down
1 change: 1 addition & 0 deletions frontend/providers/template/src/constants/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export const gpuResourceKey = 'nvidia.com/gpu';
export const templateDeployKey = 'cloud.sealos.io/deploy-on-sealos';
// db
export const kubeblocksTypeKey = 'clusterdefinition.kubeblocks.io/name';
export const dbProviderKey = 'sealos-db-provider-cr';
// labels
export const componentLabel = 'app.kubernetes.io/component';
75 changes: 70 additions & 5 deletions frontend/providers/template/src/pages/api/app/listOtherByName.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { templateDeployKey } from '@/constants/keys';
import { dbProviderKey, deployManagerKey, templateDeployKey } from '@/constants/keys';
import { authSession } from '@/services/backend/auth';
import { CRDMeta, getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { AppCrdType } from '@/types/appCRD';
import { IncomingMessage } from 'http';
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const { instanceName } = req.query as { instanceName: string };
const { namespace, k8sCore, k8sCustomObjects, k8sBatch } = await getK8s({
const { namespace, k8sCore, k8sCustomObjects, k8sBatch, k8sAuth } = await getK8s({
kubeconfig: await authSession(req.headers)
});
const labelSelector = `${templateDeployKey}=${instanceName}`;
Expand All @@ -22,6 +21,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
plural: 'apps'
};

// secret
const secretPromise = k8sCore.listNamespacedSecret(
namespace,
undefined,
Expand All @@ -31,6 +31,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
labelSelector
);

// job
const jobPromise = k8sBatch.listNamespacedJob(
namespace,
undefined,
Expand All @@ -40,6 +41,26 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
labelSelector
);

// issuer
const certIssuerPromise = k8sCustomObjects.listNamespacedCustomObject(
'cert-manager.io',
'v1',
namespace,
'issuers',
undefined,
undefined,
undefined,
undefined,
labelSelector
) as Promise<{
response: IncomingMessage;
body: {
items: { kind?: string }[];
kind: 'IssuerList';
};
}>;

// app cr
const appCrdResourcePromise = k8sCustomObjects.listNamespacedCustomObject(
appCRD.group,
appCRD.version,
Expand All @@ -53,17 +74,61 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
) as Promise<{
response: IncomingMessage;
body: {
items: AppCrdType[];
items: { kind?: string }[];
kind: 'AppList';
};
}>;

// role
const rolePromise = k8sAuth.listNamespacedRole(
namespace,
undefined,
undefined,
undefined,
undefined,
`${labelSelector},!${dbProviderKey}`
);
const roleBindingPromise = k8sAuth.listNamespacedRoleBinding(
namespace,
undefined,
undefined,
undefined,
undefined,
`${labelSelector},!${dbProviderKey}`
);
const saPromise = k8sCore.listNamespacedServiceAccount(
namespace,
undefined,
undefined,
undefined,
undefined,
`${labelSelector},!${dbProviderKey}`
);
const configMapPromise = k8sCore.listNamespacedConfigMap(
namespace,
undefined,
undefined,
undefined,
undefined,
`${labelSelector},!${dbProviderKey},!${deployManagerKey}`
);
// ไฝฟ็”จ Promise.allSettled ่Žทๅ–ๆ‰€ๆœ‰็ป“ๆžœ [secretResult, jobResult, customResourceResult]
const result = await Promise.allSettled([secretPromise, jobPromise, appCrdResourcePromise]);
const result = await Promise.allSettled([
secretPromise,
jobPromise,
appCrdResourcePromise,
certIssuerPromise,
rolePromise,
roleBindingPromise,
saPromise,
configMapPromise
]);

const data = result
.map((res) => {
if (res.status === 'fulfilled') {
return res.value.body.items.map((item) => {
// console.log(item, '==');
return {
...item,
kind: item.kind ? item.kind : res.value?.body?.kind?.replace('List', '')
Expand Down
27 changes: 27 additions & 0 deletions frontend/providers/template/src/pages/api/resource/delConfigMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { ApiResp } from '@/services/kubernet';
import { authSession } from '@/services/backend/auth';
import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const { instanceName } = req.query as { instanceName: string };
if (!instanceName) {
throw new Error('deploy name is empty');
}

const { namespace, k8sCore } = await getK8s({
kubeconfig: await authSession(req.headers)
});

const result = await k8sCore.deleteNamespacedConfigMap(instanceName, namespace);

jsonRes(res, { data: result });
} catch (err: any) {
jsonRes(res, {
code: 500,
error: err
});
}
}
27 changes: 27 additions & 0 deletions frontend/providers/template/src/pages/api/resource/delRole.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { ApiResp } from '@/services/kubernet';
import { authSession } from '@/services/backend/auth';
import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const { instanceName } = req.query as { instanceName: string };
if (!instanceName) {
throw new Error('deploy name is empty');
}

const { namespace, k8sAuth } = await getK8s({
kubeconfig: await authSession(req.headers)
});

const result = await k8sAuth.deleteNamespacedRole(instanceName, namespace);

jsonRes(res, { data: result });
} catch (err: any) {
jsonRes(res, {
code: 500,
error: err
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { ApiResp } from '@/services/kubernet';
import { authSession } from '@/services/backend/auth';
import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const { instanceName } = req.query as { instanceName: string };
if (!instanceName) {
throw new Error('deploy name is empty');
}

const { namespace, k8sAuth } = await getK8s({
kubeconfig: await authSession(req.headers)
});

const result = await k8sAuth.deleteClusterRoleBinding(instanceName, namespace);

jsonRes(res, { data: result });
} catch (err: any) {
jsonRes(res, {
code: 500,
error: err
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { ApiResp } from '@/services/kubernet';
import { authSession } from '@/services/backend/auth';
import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const { instanceName } = req.query as { instanceName: string };
if (!instanceName) {
throw new Error('deploy name is empty');
}

const { namespace, k8sCore } = await getK8s({
kubeconfig: await authSession(req.headers)
});

const result = await k8sCore.deleteNamespacedServiceAccount(instanceName, namespace);

jsonRes(res, { data: result });
} catch (err: any) {
jsonRes(res, {
code: 500,
error: err
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,28 @@ import { jsonRes } from '@/services/backend/response';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const { namespace } = req.query as { namespace: string };
const { k8sCustomObjects } = await getK8s({
const { instanceName } = req.query as { instanceName: string };
const { k8sCustomObjects, namespace } = await getK8s({
kubeconfig: await authSession(req.headers)
});

const customResource: CRDMeta = {
group: 'app.sealos.io',
group: 'cert-manager.io',
version: 'v1',
namespace: namespace,
plural: 'apps'
plural: 'issuers'
};

// ่Žทๅ–ๆŒ‡ๅฎšๅ‘ฝๅ็ฉบ้—ดไธญ็š„ๆ‰€ๆœ‰่‡ชๅฎšไน‰่ต„ๆบ
const customResourceList = await k8sCustomObjects.listNamespacedCustomObject(
// ๅˆ ้™คๆŒ‡ๅฎšๅ็งฐ็š„่‡ชๅฎšไน‰่ต„ๆบ
const reuslt = await k8sCustomObjects.deleteNamespacedCustomObject(
customResource.group,
customResource.version,
customResource.namespace,
customResource.plural
customResource.plural,
instanceName
);

jsonRes(res, { data: customResourceList, message: 'retrieved successfully' });
jsonRes(res, { data: reuslt });
} catch (err: any) {
jsonRes(res, {
code: 500,
Expand Down
Loading