From 48f9c4b83a05579e9f5e1fadcf4441ff7c165577 Mon Sep 17 00:00:00 2001 From: Desert Otter Date: Tue, 19 Dec 2023 14:29:13 +0800 Subject: [PATCH 01/38] bugfix: fix sudo -E '' with an helm cmd has single quotation (#4427) --- pkg/ssh/sshcmd.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/ssh/sshcmd.go b/pkg/ssh/sshcmd.go index ad28425db01..8c025f5818c 100644 --- a/pkg/ssh/sshcmd.go +++ b/pkg/ssh/sshcmd.go @@ -38,10 +38,15 @@ func (c *Client) Ping(host string) error { } func (c *Client) wrapCommands(cmds ...string) string { + cmdJoined := strings.Join(cmds, "; ") if !c.Option.sudo || c.Option.user == defaultUsername { - return strings.Join(cmds, "; ") + return cmdJoined } - return fmt.Sprintf("sudo -E /bin/bash -c '%s'", strings.Join(cmds, "; ")) + + // Escape single quotes in cmd, fix https://github.com/labring/sealos/issues/4424 + // e.g. echo 'hello world' -> `sudo -E /bin/bash -c 'echo "hello world"'` + cmdEscaped := strings.ReplaceAll(cmdJoined, `'`, `"`) + return fmt.Sprintf("sudo -E /bin/bash -c '%s'", cmdEscaped) } func (c *Client) CmdAsyncWithContext(ctx context.Context, host string, cmds ...string) error { From 3677c36299d7418fc9c8fff065fc39cfbaf5e1d4 Mon Sep 17 00:00:00 2001 From: Jiahui <4543bxy@gmail.com> Date: Tue, 19 Dec 2023 14:30:28 +0800 Subject: [PATCH 02/38] Optimize/remote cmd return error (#4407) * Optimize remote execution command return error message * fix k3s delete cluster --- pkg/runtime/k3s/lifecycle.go | 3 +-- pkg/ssh/remote.go | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/runtime/k3s/lifecycle.go b/pkg/runtime/k3s/lifecycle.go index 9015297e934..7b362cab879 100644 --- a/pkg/runtime/k3s/lifecycle.go +++ b/pkg/runtime/k3s/lifecycle.go @@ -62,8 +62,7 @@ func (k *K3s) resetNode(host string) error { logger.Error("failed to clean node, exec command %s failed, %v", removeKubeConfig, removeKubeConfigErr) } if slices.Contains(k.cluster.GetNodeIPAndPortList(), host) { - vipAndPort := fmt.Sprintf("%s:%d", k.cluster.GetVIP(), k.config.APIServerPort) - ipvsclearErr := k.remoteUtil.IPVSClean(host, vipAndPort) + ipvsclearErr := k.remoteUtil.IPVSClean(host, k.getVipAndPort()) if ipvsclearErr != nil { logger.Error("failed to clear ipvs rules for node %s: %v", host, ipvsclearErr) } diff --git a/pkg/ssh/remote.go b/pkg/ssh/remote.go index b455f80a404..ac077bcdc4b 100644 --- a/pkg/ssh/remote.go +++ b/pkg/ssh/remote.go @@ -191,7 +191,10 @@ func NewRemoteFromSSH(clusterName string, sshInterface Interface) *Remote { func (s *Remote) executeRemoteUtilSubcommand(ip, cmd string) error { cmd = fmt.Sprintf("%s %s", s.pathResolver.RootFSSealctlPath(), cmd) - return s.execer.CmdAsync(ip, cmd) + if err := s.execer.CmdAsync(ip, cmd); err != nil { + return fmt.Errorf("failed to execute remote command `%s`: %v", cmd, err) + } + return nil } func (s *Remote) outputRemoteUtilSubcommand(ip, cmd string) (string, error) { From 97c3ad2c164f1b3c978e151ccbb15cc52c24b240 Mon Sep 17 00:00:00 2001 From: yy <56745951+lingdie@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:16:16 +0800 Subject: [PATCH 03/38] chore: fix version/price/env (#4435) * chore: set env for desktop to enable sign up * Update install.sh * Update resources.go change nodeport unit price * Update resources.go --------- Co-authored-by: Jiahui <4543bxy@gmail.com> --- controllers/pkg/resources/resources.go | 4 ++-- frontend/desktop/deploy/Kubefile | 2 +- scripts/cloud/install.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/controllers/pkg/resources/resources.go b/controllers/pkg/resources/resources.go index f9a78881e05..6bfd569bf62 100644 --- a/controllers/pkg/resources/resources.go +++ b/controllers/pkg/resources/resources.go @@ -267,8 +267,8 @@ var DefaultPropertyTypeList = []PropertyType{ Name: "services.nodeports", Enum: 4, PriceType: AVG, - UnitPrice: 10, - ViewPrice: 10000, + UnitPrice: 2.083, + ViewPrice: 2083, UnitString: "1", }, } diff --git a/frontend/desktop/deploy/Kubefile b/frontend/desktop/deploy/Kubefile index fe843c582ce..dc7b99afec5 100644 --- a/frontend/desktop/deploy/Kubefile +++ b/frontend/desktop/deploy/Kubefile @@ -12,7 +12,7 @@ ENV passWordEnabled="false" ENV githubEnabled="false" ENV wechatEnabled="false" ENV smsEnabled="false" -ENV signUpEnabled="false" +ENV signUpEnabled="true" ENV apiEnabled="false" CMD ["bash scripts/init.sh"] diff --git a/scripts/cloud/install.sh b/scripts/cloud/install.sh index 3699ed76842..28bff4f11c4 100644 --- a/scripts/cloud/install.sh +++ b/scripts/cloud/install.sh @@ -4,7 +4,7 @@ set -e # Configurations CLOUD_DIR="/root/.sealos/cloud" -SEALOS_VERSION="v4.3.5" +SEALOS_VERSION="v4.3.7" cloud_version="latest" #mongodb_version="mongodb-5.0" #master_ips= From 8069caa36bab6b6dcbeced52f73d2895cfc3612c Mon Sep 17 00:00:00 2001 From: zhujingyang <72259332+zjy365@users.noreply.github.com> Date: Wed, 20 Dec 2023 14:57:45 +0800 Subject: [PATCH 04/38] feat:launchpad jsonpatch & template add filename (#4436) * feat:launchpad jsonpatch & template add filename Signed-off-by: jingyang <3161362058@qq.com> * add db services.nodeports price Signed-off-by: jingyang <3161362058@qq.com> --------- Signed-off-by: jingyang <3161362058@qq.com> --- .../desktop/public/locales/en/common.json | 3 +- .../desktop/public/locales/zh/common.json | 5 +- .../desktop/src/components/account/index.tsx | 2 +- .../src/components/app_window/index.tsx | 16 +++- .../src/pages/api/platform/authCname.ts | 1 + .../src/pages/app/edit/components/Form.tsx | 22 +++-- .../applaunchpad/src/pages/app/edit/index.tsx | 7 +- .../applaunchpad/src/utils/deployYaml2Json.ts | 17 ++-- .../providers/applaunchpad/src/utils/tools.ts | 94 +++++-------------- .../src/pages/api/platform/resourcePrice.ts | 7 +- .../db/detail/components/AppBaseInfo.tsx | 15 +-- .../providers/dbprovider/src/store/static.ts | 3 +- .../template/src/pages/api/getKindTemplate.ts | 44 --------- .../src/pages/api/getTemplateSource.ts | 9 +- .../template/src/pages/api/updateRepo.ts | 5 +- .../src/pages/deploy/components/Form.tsx | 11 +-- .../template/src/pages/deploy/index.tsx | 4 +- .../template/src/pages/develop/index.tsx | 2 +- frontend/providers/template/src/types/app.ts | 2 + 19 files changed, 99 insertions(+), 170 deletions(-) delete mode 100644 frontend/providers/template/src/pages/api/getKindTemplate.ts diff --git a/frontend/desktop/public/locales/en/common.json b/frontend/desktop/public/locales/en/common.json index 35ebe0c1266..5fe9581fb20 100644 --- a/frontend/desktop/public/locales/en/common.json +++ b/frontend/desktop/public/locales/en/common.json @@ -116,5 +116,6 @@ "Click on any shadow to skip": "Click on any shadow to skip", "Start your Sealos journey": "Start your Sealos journey", "gift amount": "Reward {{amount}} balance.", - "Recharge Amount": "Recharge Amount" + "Recharge Amount": "Recharge Amount", + "Doc": "Doc" } diff --git a/frontend/desktop/public/locales/zh/common.json b/frontend/desktop/public/locales/zh/common.json index 5c2bd7082a8..666549c0703 100644 --- a/frontend/desktop/public/locales/zh/common.json +++ b/frontend/desktop/public/locales/zh/common.json @@ -109,5 +109,6 @@ "start immediately": "立即开始", "Click on any shadow to skip": "点击任意阴影跳过", "Start your Sealos journey": "开始您的 Sealos 之旅", - "gift amount": "赠送 {{amount}} 余额." -} \ No newline at end of file + "gift amount": "赠送 {{amount}} 余额.", + "Doc": "文档" +} diff --git a/frontend/desktop/src/components/account/index.tsx b/frontend/desktop/src/components/account/index.tsx index 3f0962bf627..56532e0696c 100644 --- a/frontend/desktop/src/components/account/index.tsx +++ b/frontend/desktop/src/components/account/index.tsx @@ -100,7 +100,7 @@ const NsMenu = () => { w="250px" background="linear-gradient(270deg, #F1F1F1 0%, #EEE 43.75%, #ECECEC 100%)" > - + - + + {wnapp.menuData?.helpDocs && ( + { + typeof wnapp.menuData?.helpDocs === 'string' && + window.open(wnapp.menuData?.helpDocs); + }} + > + {t('Doc')} + + )} new Promise((resolve, reject) => { dns.resolveCname(customDomain, (err, address) => { + console.log(err, address); if (err) return reject(err); if (address[0] !== publicDomain) diff --git a/frontend/providers/applaunchpad/src/pages/app/edit/components/Form.tsx b/frontend/providers/applaunchpad/src/pages/app/edit/components/Form.tsx index 0d0021b15e7..161035887ee 100644 --- a/frontend/providers/applaunchpad/src/pages/app/edit/components/Form.tsx +++ b/frontend/providers/applaunchpad/src/pages/app/edit/components/Form.tsx @@ -974,16 +974,18 @@ const Form = ({ return ( {env.key} - - - {valText} - - + + + + {valText} + + + ); })} diff --git a/frontend/providers/applaunchpad/src/pages/app/edit/index.tsx b/frontend/providers/applaunchpad/src/pages/app/edit/index.tsx index 5581c00dc14..400b9c3d194 100644 --- a/frontend/providers/applaunchpad/src/pages/app/edit/index.tsx +++ b/frontend/providers/applaunchpad/src/pages/app/edit/index.tsx @@ -21,7 +21,7 @@ import { json2Service } from '@/utils/deployYaml2Json'; import { serviceSideProps } from '@/utils/i18n'; -import { getErrText, patchYamlList, patchYamlListV1 } from '@/utils/tools'; +import { getErrText, patchYamlList } from '@/utils/tools'; import { Box, Flex } from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'next-i18next'; @@ -158,10 +158,9 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) => if (appName) { const patch = patchYamlList({ formOldYamlList: formOldYamls.current.map((item) => item.value), - crYamlList: crOldYamls.current, - newYamlList: yamls + newYamlList: yamls, + crYamlList: crOldYamls.current }); - await putApp({ patch, appName, diff --git a/frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts b/frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts index 2df50b284ca..5cd1a61f051 100644 --- a/frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts +++ b/frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts @@ -1,18 +1,17 @@ -import yaml from 'js-yaml'; -import type { AppEditType, DeployKindsType } from '@/types/app'; -import { strToBase64, str2Num, pathFormat, pathToNameFormat } from '@/utils/tools'; -import { SEALOS_DOMAIN, INGRESS_SECRET } from '@/store/static'; import { - maxReplicasKey, - minReplicasKey, appDeployKey, - publicDomainKey, + deployPVCResizeKey, gpuNodeSelectorKey, gpuResourceKey, - deployPVCResizeKey + maxReplicasKey, + minReplicasKey, + publicDomainKey } from '@/constants/app'; +import { INGRESS_SECRET, SEALOS_DOMAIN } from '@/store/static'; +import type { AppEditType } from '@/types/app'; +import { pathFormat, pathToNameFormat, str2Num, strToBase64 } from '@/utils/tools'; import dayjs from 'dayjs'; -import jsonpatch, { Operation } from 'fast-json-patch'; +import yaml from 'js-yaml'; export const json2DeployCr = (data: AppEditType, type: 'deployment' | 'statefulset') => { const totalStorage = data.storeList.reduce((acc, item) => acc + item.value, 0); diff --git a/frontend/providers/applaunchpad/src/utils/tools.ts b/frontend/providers/applaunchpad/src/utils/tools.ts index 88fff9bb043..4c7dd3d567d 100644 --- a/frontend/providers/applaunchpad/src/utils/tools.ts +++ b/frontend/providers/applaunchpad/src/utils/tools.ts @@ -233,13 +233,13 @@ export const patchYamlList = ({ newYamlList: string[]; crYamlList: DeployKindsType[]; }) => { - console.log(formOldYamlList, newYamlList, crYamlList, '======='); - const oldFormJsonList = formOldYamlList .map((item) => yaml.loadAll(item)) .flat() as DeployKindsType[]; const newFormJsonList = newYamlList.map((item) => yaml.loadAll(item)).flat() as DeployKindsType[]; + console.log(oldFormJsonList, newFormJsonList, crYamlList, '===patchYamlList==='); + const actions: AppPatchPropsType = []; // find delete @@ -298,7 +298,21 @@ export const patchYamlList = ({ } /* generate new json */ - const patchResYamlJson = jsonpatch.applyPatch(crOldYamlJson, patchRes, true).newDocument; + const _patchRes: jsonpatch.Operation[] = patchRes.map((item) => { + let jsonPatchError = jsonpatch.validate([item], crOldYamlJson); + if ( + jsonPatchError?.operation && + jsonPatchError?.name === 'OPERATION_PATH_UNRESOLVABLE' + ) { + return { + ...jsonPatchError.operation, + op: 'add' + }; + } else { + return item; + } + }); + const patchResYamlJson = jsonpatch.applyPatch(crOldYamlJson, _patchRes, true).newDocument; // delete invalid field // @ts-ignore @@ -314,8 +328,7 @@ export const patchYamlList = ({ return patchResYamlJson; } catch (error) { - console.log(error); - + console.log('ACTIONS JSON ERROR\n', error); return newYamlJson; } })(); @@ -344,73 +357,18 @@ export const patchYamlList = ({ } } - actions.push({ - type: 'patch', - kind: newYamlJson.kind as `${YamlKindEnum}`, - value: actionsJson as any - }); - } else { - actions.push({ - type: 'create', - kind: newYamlJson.kind as `${YamlKindEnum}`, - value: yaml.dump(newYamlJson) - }); - } - }); - console.log(actions, 'actions'); - return actions; -}; - -export const patchYamlListV1 = ({ - newYamlList, - oldYamlList -}: { - newYamlList: string[]; - oldYamlList: DeployKindsType[]; -}) => { - const newFormJsonList = newYamlList.map((item) => yaml.loadAll(item)).flat() as DeployKindsType[]; - console.log('new:', newFormJsonList, '\n old', oldYamlList); - - const actions: AppPatchPropsType = []; - - // find delete - oldYamlList.forEach((oldYamlJson) => { - const item = newFormJsonList.find( - (item) => item.kind === oldYamlJson.kind && item.metadata?.name === oldYamlJson.metadata?.name - ); - if (!item && oldYamlJson.metadata?.name) { - actions.push({ - type: 'delete', - kind: oldYamlJson.kind as `${YamlKindEnum}`, - name: oldYamlJson.metadata?.name - }); - } - }); - - // find create and patch - newFormJsonList.forEach((newYamlJson) => { - const oldFormJson = oldYamlList.find( - (item) => - item.kind === newYamlJson.kind && item?.metadata?.name === newYamlJson?.metadata?.name - ); - - if (oldFormJson) { - // adapt service ports - if (newYamlJson.kind === YamlKindEnum.Service) { - // @ts-ignore - const ports = newYamlJson?.spec.ports || []; - - // @ts-ignore - if (ports.length > 1 && !ports[0]?.name) { - // @ts-ignore - newYamlJson.spec.ports[0].name = 'adaptport'; - } - } + console.log( + 'patch result===', + oldFormJson.metadata?.name, + oldFormJson.kind, + patchRes, + actionsJson + ); actions.push({ type: 'patch', kind: newYamlJson.kind as `${YamlKindEnum}`, - value: newYamlJson as any + value: actionsJson as any }); } else { actions.push({ diff --git a/frontend/providers/dbprovider/src/pages/api/platform/resourcePrice.ts b/frontend/providers/dbprovider/src/pages/api/platform/resourcePrice.ts index 44fbf07598d..7988ef87433 100644 --- a/frontend/providers/dbprovider/src/pages/api/platform/resourcePrice.ts +++ b/frontend/providers/dbprovider/src/pages/api/platform/resourcePrice.ts @@ -8,6 +8,7 @@ export type Response = { cpu: number; memory: number; storage: number; + nodeports: number; }; type ResourceType = | 'cpu' @@ -18,7 +19,8 @@ type ResourceType = | 'mongodb' | 'minio' | 'infra-memory' - | 'infra-disk'; + | 'infra-disk' + | 'services.nodeports'; type PriceCrdType = { apiVersion: 'account.sealos.io/v1'; kind: 'PriceQuery'; @@ -72,7 +74,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const data = { cpu: countSourcePrice(priceResponse, 'cpu'), memory: countSourcePrice(priceResponse, 'memory'), - storage: countSourcePrice(priceResponse, 'storage') + storage: countSourcePrice(priceResponse, 'storage'), + nodeports: countSourcePrice(priceResponse, 'services.nodeports') }; 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 345ad320ead..dbac6e0e802 100644 --- a/frontend/providers/dbprovider/src/pages/db/detail/components/AppBaseInfo.tsx +++ b/frontend/providers/dbprovider/src/pages/db/detail/components/AppBaseInfo.tsx @@ -9,6 +9,7 @@ import MyIcon from '@/components/Icon'; import { DBStatusEnum, DBTypeEnum, DBTypeSecretMap, defaultDBDetail } from '@/constants/db'; import { useToast } from '@/hooks/useToast'; import useEnvStore from '@/store/env'; +import { SOURCE_PRICE } from '@/store/static'; import type { DBDetailType } from '@/types/db'; import { json2NetworkService } from '@/utils/json2Yaml'; import { printMemory, useCopyData } from '@/utils/tools'; @@ -395,21 +396,9 @@ const AppBaseInfo = ({ db = defaultDBDetail }: { db: DBDetailType }) => { {t('Billing Standards')}
- 0.5 + {SOURCE_PRICE.nodeports} / {t('Hour')}
- {/*
window.open('https://forum.laf.run/d/1092')} - > - - 免费方案 -
*/} diff --git a/frontend/providers/dbprovider/src/store/static.ts b/frontend/providers/dbprovider/src/store/static.ts index daffd2bf0ea..c4415c27fc3 100644 --- a/frontend/providers/dbprovider/src/store/static.ts +++ b/frontend/providers/dbprovider/src/store/static.ts @@ -6,7 +6,8 @@ import type { Response as resourcePriceResponse } from '@/pages/api/platform/res export let SOURCE_PRICE: resourcePriceResponse = { cpu: 0.067, memory: 0.033792, - storage: 0.002048 + storage: 0.002048, + nodeports: 0.5 }; export let INSTALL_ACCOUNT = false; diff --git a/frontend/providers/template/src/pages/api/getKindTemplate.ts b/frontend/providers/template/src/pages/api/getKindTemplate.ts deleted file mode 100644 index 93d6a783113..00000000000 --- a/frontend/providers/template/src/pages/api/getKindTemplate.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { authSession } from '@/services/backend/auth'; -import { getK8s } from '@/services/backend/kubernetes'; -import { jsonRes } from '@/services/backend/response'; -import { ApiResp } from '@/services/kubernet'; -import { TemplateType } from '@/types/app'; -import fs from 'fs'; -import yaml from 'js-yaml'; -import type { NextApiRequest, NextApiResponse } from 'next'; -import path from 'path'; - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - try { - const { templateName } = req.query as { templateName: string }; - let user_namespace = ''; - - try { - const { namespace } = await getK8s({ - kubeconfig: await authSession(req.headers) - }); - user_namespace = namespace; - } catch (error) { - console.log(error, 'errpr-'); - } - - const originalPath = process.cwd(); - const targetPath = path.resolve(originalPath, 'FastDeployTemplates', 'template'); - const yamlString = fs.readFileSync(`${targetPath}/${templateName}.yaml`, 'utf-8'); - const yamlData = yaml.loadAll(yamlString); - const templateYaml: TemplateType = yamlData.find( - (item: any) => item.kind === 'Template' - ) as TemplateType; - - jsonRes(res, { - code: 200, - data: templateYaml - }); - } catch (err: any) { - console.log(err); - jsonRes(res, { - code: 500, - error: err - }); - } -} diff --git a/frontend/providers/template/src/pages/api/getTemplateSource.ts b/frontend/providers/template/src/pages/api/getTemplateSource.ts index 0ef0cf3a1e2..29be8f0535e 100644 --- a/frontend/providers/template/src/pages/api/getTemplateSource.ts +++ b/frontend/providers/template/src/pages/api/getTemplateSource.ts @@ -13,6 +13,7 @@ import { replaceRawWithCDN } from './listTemplate'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { const { templateName } = req.query as { templateName: string }; + let user_namespace = ''; try { @@ -72,8 +73,12 @@ export async function GetTemplateByName({ const originalPath = process.cwd(); const targetPath = path.resolve(originalPath, 'FastDeployTemplates', 'template'); - - const yamlString = fs.readFileSync(`${targetPath}/${templateName}.yaml`, 'utf-8'); + // Query by file name in template details + const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json'); + const jsonData: TemplateType[] = JSON.parse(fs.readFileSync(jsonPath, 'utf8')); + const _tempalte = jsonData.find((item) => item.metadata.name === templateName); + const _tempalteName = _tempalte ? _tempalte.spec.fileName : `${templateName}.yaml`; + const yamlString = fs.readFileSync(`${targetPath}/${_tempalteName}`, 'utf-8'); const yamlData = yaml.loadAll(yamlString); const templateYaml: TemplateType = yamlData.find( diff --git a/frontend/providers/template/src/pages/api/updateRepo.ts b/frontend/providers/template/src/pages/api/updateRepo.ts index bb5a1ee069d..bb0cd1e9452 100644 --- a/frontend/providers/template/src/pages/api/updateRepo.ts +++ b/frontend/providers/template/src/pages/api/updateRepo.ts @@ -1,5 +1,6 @@ import { jsonRes } from '@/services/backend/response'; import { ApiResp } from '@/services/kubernet'; +import { TemplateType } from '@/types/app'; import { exec } from 'child_process'; import fs from 'fs'; import JSYAML from 'js-yaml'; @@ -65,9 +66,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< fileList.forEach((item: any) => { try { if (!item) return; + const fileName = path.basename(item); const content = fs.readFileSync(item, 'utf-8'); - const yamlTemplate: any = JSYAML.loadAll(content)[0]; + const yamlTemplate = JSYAML.loadAll(content)[0] as TemplateType; if (!!yamlTemplate) { + yamlTemplate.spec['fileName'] = fileName; jsonObjArr.push(yamlTemplate); } } catch (error) { diff --git a/frontend/providers/template/src/pages/deploy/components/Form.tsx b/frontend/providers/template/src/pages/deploy/components/Form.tsx index e57d60e0bd4..60b27634707 100644 --- a/frontend/providers/template/src/pages/deploy/components/Form.tsx +++ b/frontend/providers/template/src/pages/deploy/components/Form.tsx @@ -62,8 +62,7 @@ const Form = ({ w="200px" className="template-dynamic-label" color={'#333'} - userSelect={'none'} - > + userSelect={'none'}> {item?.label} {item?.required && ( @@ -79,7 +78,7 @@ const Form = ({ autoFocus={true} placeholder={item?.description} {...register(item?.key, { - required: item?.required + required: item?.required ? `${item.label} is required` : '' })} />
@@ -93,16 +92,14 @@ const Form = ({ alignItems="center" h={'160px'} w={'100%'} - flexDirection="column" - > + flexDirection="column"> + alignItems={'center'}> diff --git a/frontend/providers/template/src/pages/deploy/index.tsx b/frontend/providers/template/src/pages/deploy/index.tsx index 0af72834bd6..73bada34609 100644 --- a/frontend/providers/template/src/pages/deploy/index.tsx +++ b/frontend/providers/template/src/pages/deploy/index.tsx @@ -162,8 +162,8 @@ export default function EditApp({ appName }: { appName?: string }) { setIsLoading(false); }; - const submitError = () => { - formHook.getValues(); + const submitError = async () => { + await formHook.trigger(); toast({ title: deepSearch(formHook.formState.errors), status: 'error', diff --git a/frontend/providers/template/src/pages/develop/index.tsx b/frontend/providers/template/src/pages/develop/index.tsx index 4c2cd28a5ea..b0abfc84176 100644 --- a/frontend/providers/template/src/pages/develop/index.tsx +++ b/frontend/providers/template/src/pages/develop/index.tsx @@ -56,7 +56,7 @@ export default function Develop() { const onYamlChange = debounce((state: EditorState) => { const value = state.doc.toString(); parseTemplate(value); - }, 1000); + }, 500); const getYamlSource = (str: string): TemplateSourceType => { const yamlData = JsYaml.loadAll(str); diff --git a/frontend/providers/template/src/types/app.ts b/frontend/providers/template/src/types/app.ts index d601482f8a8..f765353db6f 100644 --- a/frontend/providers/template/src/types/app.ts +++ b/frontend/providers/template/src/types/app.ts @@ -7,6 +7,8 @@ export type TemplateType = { spec: { gitRepo: string; // new templateType: 'inline'; // new + fileName: string; // new + template_type?: string; author: string; title: string; From 63efb79446560c86d98c8200d6258ebbbfbea09e Mon Sep 17 00:00:00 2001 From: yy <56745951+lingdie@users.noreply.github.com> Date: Thu, 21 Dec 2023 12:25:20 +0800 Subject: [PATCH 05/38] chore: add monitor for database and kubernetes. (#4438) Signed-off-by: yy --- deploy/cloud/manifests/tls-secret.yaml | 5 - scripts/cloud/install.sh | 173 ++++++++++++++++++++++++- 2 files changed, 170 insertions(+), 8 deletions(-) diff --git a/deploy/cloud/manifests/tls-secret.yaml b/deploy/cloud/manifests/tls-secret.yaml index 5e70be9a70c..b1e4c16fea1 100644 --- a/deploy/cloud/manifests/tls-secret.yaml +++ b/deploy/cloud/manifests/tls-secret.yaml @@ -6,11 +6,6 @@ data: kind: Secret metadata: - annotations: - reflector.v1.k8s.emberstack.com/reflection-allowed: "true" - reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: sealos,\w+-system,\w+-frontend,ns-[\-a-z0-9]* - reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true" - reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: sealos,\w+-system,\w+-frontend,ns-[\-a-z0-9]* name: wildcard-cert namespace: sealos-system type: kubernetes.io/tls diff --git a/scripts/cloud/install.sh b/scripts/cloud/install.sh index 28bff4f11c4..fccd7622409 100644 --- a/scripts/cloud/install.sh +++ b/scripts/cloud/install.sh @@ -26,10 +26,10 @@ cilium_version=${cilium_version:-"1.12.14"} cert_manager_version=${cert_manager_version:-"1.8.0"} helm_version=${helm_version:-"3.12.0"} openebs_version=${openebs_version:-"3.4.0"} -reflector_version=${reflector_version:-"7.0.151"} ingress_nginx_version=${ingress_nginx_version:-"1.5.1"} kubeblocks_version=${kubeblocks_version:-"0.6.4"} metrics_server_version=${metrics_server_version:-"0.6.4"} +kube_prometheus_stack_version=${kube_prometheus_stack_version:-"0.63.0"} # Define English and Chinese prompts @@ -54,6 +54,7 @@ PROMPTS_EN=( ["enter_choice"]="Please enter your choice (zh/en): " ["k8s_installation"]="Installing Kubernetes cluster." ["ingress_installation"]="Installing Ingress-nginx-controller and Kubeblocks." + ["installing_monitoring"]="Installing kubernetes monitoring." ["patching_ingress"]="Modifying the tolerance of Ingress-nginx-controller to allow it to run on the master node." ["installing_cloud"]="Installing Sealos Cloud." ["avx_not_supported"]="CPU does not support AVX instruction set." @@ -115,6 +116,7 @@ PROMPTS_CN=( ["enter_choice"]="请输入您的选择 (zh/en): " ["k8s_installation"]="正在安装 Kubernetes 集群." ["ingress_installation"]="正在安装 Ingress-nginx-controller 和 Kubeblocks." + ["installing_monitoring"]="正在安装 kubernetes 监控." ["patching_ingress"]="正在修改 Ingress-nginx-controller 的容忍度, 以允许它在主节点上运行." ["installing_cloud"]="正在安装 Sealos Cloud." ["avx_not_supported"]="CPU 不支持 AVX 指令集." @@ -373,6 +375,165 @@ spec: " echo "$ingress_config" > $CLOUD_DIR/ingress-nginx-config.yaml + kb_addon_prometheus_server_patch=' +data: + prometheus.yml: | + global: + evaluation_interval: 15s + scrape_interval: 15s + scrape_timeout: 10s + rule_files: + - /etc/config/recording_rules.yml + - /etc/config/alerting_rules.yml + - /etc/config/mysql_alert_rules.yml + - /etc/config/postgresql_alert_rules.yml + - /etc/config/redis_alert_rules.yml + - /etc/config/kafka_alert_rules.yml + - /etc/config/mongodb_replicaset_alert_rules.yaml + scrape_configs: + - job_name: prometheus + static_configs: + - targets: + - localhost:9090 + - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + job_name: kubernetes-apiservers + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - action: keep + regex: default;kubernetes;https + source_labels: + - __meta_kubernetes_namespace + - __meta_kubernetes_service_name + - __meta_kubernetes_endpoint_port_name + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true + - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + job_name: kubernetes-nodes + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - replacement: kubernetes.default.svc:443 + target_label: __address__ + - regex: (.+) + replacement: /api/v1/nodes/$1/proxy/metrics + source_labels: + - __meta_kubernetes_node_name + target_label: __metrics_path__ + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true + - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + job_name: kubernetes-nodes-cadvisor + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - replacement: kubernetes.default.svc:443 + target_label: __address__ + - regex: (.+) + replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor + source_labels: + - __meta_kubernetes_node_name + target_label: __metrics_path__ + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true + - honor_labels: true + job_name: kubeblocks-service-endpoints + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - action: keep + regex: kubeblocks + source_labels: + - __meta_kubernetes_service_label_app_kubernetes_io_managed_by + - action: keep + regex: true + source_labels: + - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_scrape + - action: drop + regex: true + source_labels: + - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_scrape_slow + - action: replace + regex: (https?) + source_labels: + - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_scheme + target_label: __scheme__ + - action: replace + regex: (.+) + source_labels: + - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_path + target_label: __metrics_path__ + - action: replace + regex: (.+?)(?::\d+)?;(\d+) + replacement: $1:$2 + source_labels: + - __address__ + - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_port + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_service_annotation_monitor_kubeblocks_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_service_name + target_label: service + - action: replace + source_labels: + - __meta_kubernetes_pod_node_name + target_label: node + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: pod + - action: drop + regex: Pending|Succeeded|Failed|Completed + source_labels: + - __meta_kubernetes_pod_phase + scrape_interval: 5m + scrape_timeout: 30s + alerting: + alertmanagers: + - kubernetes_sd_configs: + - role: pod + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + relabel_configs: + - source_labels: [__meta_kubernetes_namespace] + regex: kb-system + action: keep + - source_labels: [__meta_kubernetes_pod_label_app] + regex: prometheus + action: keep + - source_labels: [__meta_kubernetes_pod_label_component] + regex: alertmanager + action: keep + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_probe] + regex: .* + action: keep + - source_labels: [__meta_kubernetes_pod_container_port_number] + regex: "9093" + action: keep +' + echo $kb_addon_prometheus_server_patch > $CLOUD_DIR/kb-addon-prometheus-server-patch.yaml + + sealos_gen_cmd="sealos gen ${image_registry}/${image_repository}/kubernetes:v${kubernetes_version#v:-1.25.6}\ ${master_ips:+--masters $master_ips}\ ${node_ips:+--nodes $node_ips}\ @@ -434,12 +595,18 @@ volumeBindingMode: WaitForFirstConsumer EOF get_prompt "ingress_installation" - sealos run ${image_registry}/${image_repository}/kubernetes-reflector:v${reflector_version#v:-7.0.151}\ - ${image_registry}/${image_repository}/ingress-nginx:v${ingress_nginx_version#v:-1.5.1}\ + sealos run ${image_registry}/${image_repository}/ingress-nginx:v${ingress_nginx_version#v:-1.5.1}\ ${image_registry}/${image_repository}/kubeblocks:v${kubeblocks_version#v:-0.6.2}\ --config-file $CLOUD_DIR/ingress-nginx-config.yaml + kbcli addon enable prometheus + + get_prompt "installing_monitoring" + sealos run "${image_registry}/${image_repository}/metrics-server:v${metrics_server_version#v:-0.6.4}" + sealos run "${image_registry}/${image_repository}/kube-prometheus-stack:v${kube_prometheus_stack_version#v:-0.63.0}" + + kubectl patch cm kb-addon-prometheus-server -n kb-system --patch-file $CLOUD_DIR/kb-addon-prometheus-server-patch.yaml get_prompt "patching_ingress" kubectl -n ingress-nginx patch ds ingress-nginx-controller -p '{"spec":{"template":{"spec":{"tolerations":[{"key":"node-role.kubernetes.io/control-plane","operator":"Exists","effect":"NoSchedule"}]}}}}' From 937d8295e6123dce1dc714a1c50b65fe9de7c54b Mon Sep 17 00:00:00 2001 From: yy <56745951+lingdie@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:13:21 +0800 Subject: [PATCH 06/38] chore: fix pull image. (#4439) * chore: add monitor for database and kubernetes. Signed-off-by: yy --------- Signed-off-by: yy --- scripts/cloud/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cloud/install.sh b/scripts/cloud/install.sh index fccd7622409..c19b4a9ad59 100644 --- a/scripts/cloud/install.sh +++ b/scripts/cloud/install.sh @@ -254,7 +254,7 @@ init() { pull_image "ingress-nginx" "v${ingress_nginx_version#v:-1.5.1}" pull_image "kubeblocks" "v${kubeblocks_version#v:-0.6.2}" pull_image "metrics-server" "v${metrics_server_version#v:-0.6.4}" - pull_image "kubernetes-reflector" "v${reflector_version#v:-7.0.151}" + pull_image "kube-prometheus-stack" "v${kube_prometheus_stack_version#v:-0.63.0}" pull_image "sealos-cloud" "${cloud_version}" } From 18aff5d84a6679b5ecba5a2bbc358e633b9869b2 Mon Sep 17 00:00:00 2001 From: zhujingyang <72259332+zjy365@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:33:10 +0800 Subject: [PATCH 07/38] fix:deploy menuData helpDocs (#4437) * fix:deploy menuData helpDocs Signed-off-by: jingyang <3161362058@qq.com> * feat:db BACKUP_ENABLED Signed-off-by: jingyang <3161362058@qq.com> --------- Signed-off-by: jingyang <3161362058@qq.com> --- .../adminer/deploy/manifests/appcr.yaml.tmpl | 1 - .../deploy/manifests/appcr.yaml.tmpl | 1 - frontend/providers/dbprovider/deploy/Kubefile | 1 + .../deploy/manifests/appcr.yaml.tmpl | 1 + .../dbprovider/public/locales/en/common.json | 6 +++--- .../dbprovider/public/locales/zh/common.json | 6 +++--- .../dbprovider/src/pages/api/getEnv.ts | 4 +++- .../components/Monitor/ChartTemplate.tsx | 18 +++++++++--------- .../dbprovider/src/pages/db/detail/index.tsx | 12 ++++++------ frontend/providers/dbprovider/src/store/env.ts | 3 ++- .../src/pages/api/platform/getClusterId.ts | 4 ---- .../deploy/manifests/appcr.yaml.tmpl | 1 - .../terminal/deploy/manifests/appcr.yaml.tmpl | 1 - 13 files changed, 28 insertions(+), 31 deletions(-) diff --git a/frontend/providers/adminer/deploy/manifests/appcr.yaml.tmpl b/frontend/providers/adminer/deploy/manifests/appcr.yaml.tmpl index 9bcaed23c2a..dc19ae5b0a8 100644 --- a/frontend/providers/adminer/deploy/manifests/appcr.yaml.tmpl +++ b/frontend/providers/adminer/deploy/manifests/appcr.yaml.tmpl @@ -9,7 +9,6 @@ spec: url: "https://adminer.{{ .cloudDomain }}" icon: "https://adminer.{{ .cloudDomain }}/logo.svg" menuData: - helpDocs: https://www.sealos.io/docs/cloud/apps/adminer/ helpDropDown: false nameColor: text-black name: Adminer diff --git a/frontend/providers/costcenter/deploy/manifests/appcr.yaml.tmpl b/frontend/providers/costcenter/deploy/manifests/appcr.yaml.tmpl index 5b816bd45c3..1991fbb698a 100644 --- a/frontend/providers/costcenter/deploy/manifests/appcr.yaml.tmpl +++ b/frontend/providers/costcenter/deploy/manifests/appcr.yaml.tmpl @@ -14,7 +14,6 @@ spec: zh-Hans: name: 费用中心 menuData: - helpDocs: https://www.sealos.io/docs/cloud/apps/costcenter/ helpDropDown: false nameColor: text-black name: Cost Center diff --git a/frontend/providers/dbprovider/deploy/Kubefile b/frontend/providers/dbprovider/deploy/Kubefile index d7e06cb05b8..955b99c04aa 100644 --- a/frontend/providers/dbprovider/deploy/Kubefile +++ b/frontend/providers/dbprovider/deploy/Kubefile @@ -15,5 +15,6 @@ ENV minioSecretKey="" ENV minioPort="" ENV migrateFileImage="" ENV minioBucketName="" +ENV BACKUP_ENABLED="false" CMD ["kubectl apply -f manifests"] diff --git a/frontend/providers/dbprovider/deploy/manifests/appcr.yaml.tmpl b/frontend/providers/dbprovider/deploy/manifests/appcr.yaml.tmpl index 0180fa51770..e5da49bf4c7 100644 --- a/frontend/providers/dbprovider/deploy/manifests/appcr.yaml.tmpl +++ b/frontend/providers/dbprovider/deploy/manifests/appcr.yaml.tmpl @@ -14,6 +14,7 @@ spec: zh-Hans: name: 数据库 menuData: + helpDocs: https://sealos.run/docs/guides/dbprovider/config-docs/ helpDropDown: false nameColor: text-black name: Database diff --git a/frontend/providers/dbprovider/public/locales/en/common.json b/frontend/providers/dbprovider/public/locales/en/common.json index a603e313c70..28fdec83fc2 100644 --- a/frontend/providers/dbprovider/public/locales/en/common.json +++ b/frontend/providers/dbprovider/public/locales/en/common.json @@ -144,8 +144,8 @@ "Migrate": "Migrate", "Advanced Configuration": "Advanced Configuration", "Option": "Option", - "Internet Migration": "Internet Migration", - "File Migration": "File Migration", + "Online Import": "Online Import", + "Import Through File": "Import Through File", "Source Database": "Source Database", "Database Host": "Database Host", "DB Name": "DataBase Name", @@ -259,4 +259,4 @@ "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?" -} +} \ 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 5e1bab23175..8f835058ea3 100644 --- a/frontend/providers/dbprovider/public/locales/zh/common.json +++ b/frontend/providers/dbprovider/public/locales/zh/common.json @@ -190,8 +190,8 @@ "Migrate": "迁移", "Advanced Configuration": "高级配置", "Option": "选填", - "Internet Migration": "公网迁移", - "File Migration": "文件迁移", + "Online Import": "在线导入", + "Import Through File": "文件导入", "Source Database": "源数据库", "Database Host": "数据库 Host", "DB Name": "数据库名字", @@ -261,4 +261,4 @@ "Failed to turn off automatic backup": "关闭自动备份失败", "Automatic backup is turned off": "已关闭自动备份", "Are you sure you want to turn off automatic backup": "确定关闭自动备份吗" -} +} \ No newline at end of file diff --git a/frontend/providers/dbprovider/src/pages/api/getEnv.ts b/frontend/providers/dbprovider/src/pages/api/getEnv.ts index cf80b6c7d56..26cad5df994 100644 --- a/frontend/providers/dbprovider/src/pages/api/getEnv.ts +++ b/frontend/providers/dbprovider/src/pages/api/getEnv.ts @@ -7,6 +7,7 @@ export type SystemEnvResponse = { env_storage_className: string; migrate_file_image: string; minio_url: string; + BACKUP_ENABLED: boolean; }; export default async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -15,7 +16,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< domain: process.env.SEALOS_DOMAIN || 'cloud.sealos.io', env_storage_className: process.env.STORAGE_CLASSNAME || 'openebs-backup', migrate_file_image: process.env.MIGRATE_FILE_IMAGE || 'ghcr.io/wallyxjh/test:7.1', - minio_url: process.env.MINIO_URL || '' + minio_url: process.env.MINIO_URL || '', + BACKUP_ENABLED: process.env.BACKUP_ENABLED === 'true' } }); } diff --git a/frontend/providers/dbprovider/src/pages/db/detail/components/Monitor/ChartTemplate.tsx b/frontend/providers/dbprovider/src/pages/db/detail/components/Monitor/ChartTemplate.tsx index cb559efae71..b7e92fbdf8e 100644 --- a/frontend/providers/dbprovider/src/pages/db/detail/components/Monitor/ChartTemplate.tsx +++ b/frontend/providers/dbprovider/src/pages/db/detail/components/Monitor/ChartTemplate.tsx @@ -85,15 +85,15 @@ const ChartTemplate = ({
) : ( - - - {t('No Data Available')} + + + {t(chartTitle)} + {unit ? `(${unit})` : ''} + + + + {t('No Data Available')} + )} diff --git a/frontend/providers/dbprovider/src/pages/db/detail/index.tsx b/frontend/providers/dbprovider/src/pages/db/detail/index.tsx index 371f609ecda..54c33d0fe09 100644 --- a/frontend/providers/dbprovider/src/pages/db/detail/index.tsx +++ b/frontend/providers/dbprovider/src/pages/db/detail/index.tsx @@ -44,17 +44,17 @@ const AppDetail = ({ const { listNav } = useMemo(() => { const PublicNetMigration = ['postgresql', 'apecloud-mysql', 'mongodb'].includes(dbType); const MigrateSupported = ['postgresql', 'mongodb', 'apecloud-mysql'].includes(dbType); - const BackupSupported = ['postgresql', 'mongodb', 'apecloud-mysql', 'redis'].includes(dbType); + const BackupSupported = + ['postgresql', 'mongodb', 'apecloud-mysql', 'redis'].includes(dbType) && + SystemEnv.BACKUP_ENABLED; const listNavValue = [ { label: 'Monitor List', value: TabEnum.monitor }, { label: 'Replicas List', value: TabEnum.pod }, ...(BackupSupported ? [{ label: 'Backup List', value: TabEnum.backup }] : []), - ...(PublicNetMigration - ? [{ label: 'Internet Migration', value: TabEnum.InternetMigration }] - : []), + ...(PublicNetMigration ? [{ label: 'Online Import', value: TabEnum.InternetMigration }] : []), ...(PublicNetMigration && !!SystemEnv.minio_url - ? [{ label: 'File Migration', value: TabEnum.DumpImport }] + ? [{ label: 'Import Through File', value: TabEnum.DumpImport }] : []) ]; @@ -64,7 +64,7 @@ const AppDetail = ({ isBackupSupported: BackupSupported, listNav: listNavValue }; - }, [SystemEnv.minio_url, dbType]); + }, [SystemEnv, dbType]); const theme = useTheme(); const { toast } = useToast(); diff --git a/frontend/providers/dbprovider/src/store/env.ts b/frontend/providers/dbprovider/src/store/env.ts index 026f74cb5f7..eeffd3e03f3 100644 --- a/frontend/providers/dbprovider/src/store/env.ts +++ b/frontend/providers/dbprovider/src/store/env.ts @@ -17,7 +17,8 @@ const useEnvStore = create()( domain: '', env_storage_className: '', migrate_file_image: '', - minio_url: '' + minio_url: '', + BACKUP_ENABLED: false }, initSystemEnv: async () => { try { diff --git a/frontend/providers/license/src/pages/api/platform/getClusterId.ts b/frontend/providers/license/src/pages/api/platform/getClusterId.ts index 6c5c54886fd..098d66b05bb 100644 --- a/frontend/providers/license/src/pages/api/platform/getClusterId.ts +++ b/frontend/providers/license/src/pages/api/platform/getClusterId.ts @@ -7,10 +7,6 @@ import type { NextApiRequest, NextApiResponse } from 'next'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { - const { namespace } = await getK8s({ - kubeconfig: await authSession(req) - }); - const defaultKc = K8sApiDefault(); const result = await defaultKc.makeApiClient(k8s.CoreV1Api).readNamespace('kube-system'); diff --git a/frontend/providers/objectstorage/deploy/manifests/appcr.yaml.tmpl b/frontend/providers/objectstorage/deploy/manifests/appcr.yaml.tmpl index 12e6cf7358d..9db827b0308 100644 --- a/frontend/providers/objectstorage/deploy/manifests/appcr.yaml.tmpl +++ b/frontend/providers/objectstorage/deploy/manifests/appcr.yaml.tmpl @@ -14,7 +14,6 @@ spec: zh-Hans: name: 对象存储 menuData: - helpDocs: https://www.sealos.io/docs/cloud/apps/objectstorage/ helpDropDown: false nameColor: text-black name: Object Storage diff --git a/frontend/providers/terminal/deploy/manifests/appcr.yaml.tmpl b/frontend/providers/terminal/deploy/manifests/appcr.yaml.tmpl index 0c9d553c4bd..3385bcc5713 100644 --- a/frontend/providers/terminal/deploy/manifests/appcr.yaml.tmpl +++ b/frontend/providers/terminal/deploy/manifests/appcr.yaml.tmpl @@ -14,7 +14,6 @@ spec: zh-Hans: name: 终端 menuData: - helpDocs: https://www.sealos.io/docs/cloud/apps/terminal/ helpDropDown: false nameColor: text-black name: Terminal From c0660dbc590900a99ee1b6e8681f55af30df5274 Mon Sep 17 00:00:00 2001 From: yy <56745951+lingdie@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:51:59 +0800 Subject: [PATCH 08/38] chore: fix database monitor. (#4440) * chore: add monitor for database and kubernetes. Signed-off-by: yy Signed-off-by: yy * chore: add monitor for database and kubernetes. Signed-off-by: yy Signed-off-by: yy * chore: fix pull image logic. Signed-off-by: yy Signed-off-by: yy * fix offline build * chore: fix database monitor. Signed-off-by: yy Signed-off-by: yy * chore: fix kb prometheus. Signed-off-by: yy Signed-off-by: yy --------- Signed-off-by: yy --- frontend/providers/dbprovider/deploy/Kubefile | 2 +- scripts/cloud/build-offline-tar.sh | 4 +- scripts/cloud/install.sh | 94 +++++++++++++------ service/database/deploy/manifests/deploy.yaml | 3 +- 4 files changed, 69 insertions(+), 34 deletions(-) diff --git a/frontend/providers/dbprovider/deploy/Kubefile b/frontend/providers/dbprovider/deploy/Kubefile index 955b99c04aa..d55a797427f 100644 --- a/frontend/providers/dbprovider/deploy/Kubefile +++ b/frontend/providers/dbprovider/deploy/Kubefile @@ -8,7 +8,7 @@ COPY manifests manifests ENV cloudDomain="127.0.0.1.nip.io" ENV cloudPort="" ENV certSecretName="wildcard-cert" -ENV monitorUrl="" +ENV monitorUrl="http://database-monitor.sealos.svc.cluster.local:9090" ENV minioUrl="" ENV minioAccessKey="" ENV minioSecretKey="" diff --git a/scripts/cloud/build-offline-tar.sh b/scripts/cloud/build-offline-tar.sh index 289ee9390fe..30c3d292ae2 100644 --- a/scripts/cloud/build-offline-tar.sh +++ b/scripts/cloud/build-offline-tar.sh @@ -14,7 +14,7 @@ images=( docker.io/labring/cilium:v1.12.14 docker.io/labring/cert-manager:v1.8.0 docker.io/labring/openebs:v3.4.0 - docker.io/labring/kubernetes-reflector:v7.0.151 + docker.io/labring/kube-prometheus-stack:v0.63.0 docker.io/labring/ingress-nginx:v1.5.1 docker.io/labring/kubeblocks:v0.6.4 docker.io/labring/metrics-server:v0.6.4 @@ -32,7 +32,7 @@ done # get and save cli mkdir -p output/cli -VERSION="v4.3.5" +VERSION="v4.3.7" wget https://github.com/labring/sealos/releases/download/${VERSION}/sealos_${VERSION#v}_linux_${ARCH}.tar.gz \ && tar zxvf sealos_${VERSION#v}_linux_${ARCH}.tar.gz sealos && chmod +x sealos && mv sealos output/cli diff --git a/scripts/cloud/install.sh b/scripts/cloud/install.sh index c19b4a9ad59..2e155f1ea4a 100644 --- a/scripts/cloud/install.sh +++ b/scripts/cloud/install.sh @@ -385,16 +385,76 @@ data: rule_files: - /etc/config/recording_rules.yml - /etc/config/alerting_rules.yml + - /etc/config/kubelet_alert_rules.yml - /etc/config/mysql_alert_rules.yml - /etc/config/postgresql_alert_rules.yml - /etc/config/redis_alert_rules.yml - /etc/config/kafka_alert_rules.yml - - /etc/config/mongodb_replicaset_alert_rules.yaml + - /etc/config/mongodb_alert_rules.yml scrape_configs: - job_name: prometheus static_configs: - targets: - localhost:9090 + - honor_labels: true + job_name: kubeblocks-service + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - action: keep + regex: kubeblocks + source_labels: + - __meta_kubernetes_service_label_app_kubernetes_io_managed_by + - action: drop + regex: agamotto + source_labels: + - __meta_kubernetes_service_label_monitor_kubeblocks_io_managed_by + - action: keep + regex: true + source_labels: + - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_scrape + - action: replace + regex: (https?) + source_labels: + - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_scheme + target_label: __scheme__ + - action: replace + regex: (.+) + source_labels: + - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_path + target_label: __metrics_path__ + - action: replace + regex: (.+?)(?::\d+)?;(\d+) + replacement: $1:$2 + source_labels: + - __address__ + - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_port + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_service_annotation_monitor_kubeblocks_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_service_name + target_label: service + - action: replace + source_labels: + - __meta_kubernetes_pod_node_name + target_label: node + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: pod + - action: drop + regex: Pending|Succeeded|Failed|Completed + source_labels: + - __meta_kubernetes_pod_phase - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token job_name: kubernetes-apiservers kubernetes_sd_configs: @@ -447,22 +507,18 @@ data: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true - honor_labels: true - job_name: kubeblocks-service-endpoints + job_name: kubeblocks-agamotto kubernetes_sd_configs: - role: endpoints relabel_configs: - action: keep - regex: kubeblocks + regex: agamotto source_labels: - - __meta_kubernetes_service_label_app_kubernetes_io_managed_by + - __meta_kubernetes_service_label_monitor_kubeblocks_io_managed_by - action: keep regex: true source_labels: - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_scrape - - action: drop - regex: true - source_labels: - - __meta_kubernetes_service_annotation_monitor_kubeblocks_io_scrape_slow - action: replace regex: (https?) source_labels: @@ -483,30 +539,10 @@ data: - action: labelmap regex: __meta_kubernetes_service_annotation_monitor_kubeblocks_io_param_(.+) replacement: __param_$1 - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) - - action: replace - source_labels: - - __meta_kubernetes_namespace - target_label: namespace - - action: replace - source_labels: - - __meta_kubernetes_service_name - target_label: service - - action: replace - source_labels: - - __meta_kubernetes_pod_node_name - target_label: node - - action: replace - source_labels: - - __meta_kubernetes_pod_name - target_label: pod - action: drop regex: Pending|Succeeded|Failed|Completed source_labels: - __meta_kubernetes_pod_phase - scrape_interval: 5m - scrape_timeout: 30s alerting: alertmanagers: - kubernetes_sd_configs: @@ -531,7 +567,7 @@ data: regex: "9093" action: keep ' - echo $kb_addon_prometheus_server_patch > $CLOUD_DIR/kb-addon-prometheus-server-patch.yaml + echo "$kb_addon_prometheus_server_patch" > $CLOUD_DIR/kb-addon-prometheus-server-patch.yaml sealos_gen_cmd="sealos gen ${image_registry}/${image_repository}/kubernetes:v${kubernetes_version#v:-1.25.6}\ diff --git a/service/database/deploy/manifests/deploy.yaml b/service/database/deploy/manifests/deploy.yaml index b9c95d38269..4e9b0032668 100644 --- a/service/database/deploy/manifests/deploy.yaml +++ b/service/database/deploy/manifests/deploy.yaml @@ -36,9 +36,8 @@ spec: - /manager env: - name: PROMETHEUS_SERVICE_HOST - value: http://kb-addon-prometheus-server. + value: http://kb-addon-prometheus-server.kb-system.svc.cluster.local - name: OBJECT_STORAGE_INSTANCE - value: image: ghcr.io/labring/sealos-database-service:latest imagePullPolicy: Always name: database-monitor From edde8600eefc0a23db1a39b9407a13cbe48da797 Mon Sep 17 00:00:00 2001 From: wonderful <122499469@qq.com> Date: Thu, 21 Dec 2023 16:20:44 +0800 Subject: [PATCH 09/38] Update Quick installation of Vue Apps.md (#4434) fix typo --- .../programming-languages/Quick installation of Vue Apps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/4.0/i18n/zh-Hans/examples/programming-languages/Quick installation of Vue Apps.md b/docs/4.0/i18n/zh-Hans/examples/programming-languages/Quick installation of Vue Apps.md index df805b434d4..1b9873b42e0 100644 --- a/docs/4.0/i18n/zh-Hans/examples/programming-languages/Quick installation of Vue Apps.md +++ b/docs/4.0/i18n/zh-Hans/examples/programming-languages/Quick installation of Vue Apps.md @@ -80,7 +80,7 @@ docker build -t my-vue-app . ``` -## 步骤6:登陆 Sealos +## 步骤6:登录 Sealos - 进入 [Sealos](https://cloud.sealos.io/) 官网 From 5c22d8aaef661eed0b561ff0ae3c120a329ee58e Mon Sep 17 00:00:00 2001 From: yy <56745951+lingdie@users.noreply.github.com> Date: Thu, 21 Dec 2023 18:45:12 +0800 Subject: [PATCH 10/38] chore: change deploy order. (#4441) * chore: add monitor for database and kubernetes. Signed-off-by: yy Signed-off-by: yy * chore: add monitor for database and kubernetes. Signed-off-by: yy Signed-off-by: yy * chore: fix pull image logic. Signed-off-by: yy Signed-off-by: yy * fix offline build * chore: fix database monitor. Signed-off-by: yy Signed-off-by: yy * chore: fix kb prometheus. Signed-off-by: yy Signed-off-by: yy * chore: fix deploy order problem. Signed-off-by: yy Signed-off-by: yy --------- Signed-off-by: yy --- scripts/cloud/install.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/cloud/install.sh b/scripts/cloud/install.sh index 2e155f1ea4a..ad30899656a 100644 --- a/scripts/cloud/install.sh +++ b/scripts/cloud/install.sh @@ -620,6 +620,7 @@ execute_commands() { wait_cluster_ready sealos run "${image_registry}/${image_repository}/cert-manager:v${cert_manager_version#v:-1.8.0}" sealos run "${image_registry}/${image_repository}/openebs:v${openebs_version#v:-3.4.0}" + sealos run "${image_registry}/${image_repository}/metrics-server:v${metrics_server_version#v:-0.6.4}" kubectl get sc openebs-backup > /dev/null 2>&1 || kubectl create -f - < Date: Fri, 22 Dec 2023 14:37:24 +0800 Subject: [PATCH 11/38] chore(costcenter):Update copywriting for Port (#4443) --- frontend/packages/driver/src/utils.ts | 23 ++++++++------ .../workload/deployment/deployment-detail.tsx | 2 +- .../providers/applaunchpad/next.config.js | 18 +++++------ frontend/providers/applaunchpad/tsconfig.json | 19 +++--------- .../costcenter/public/locales/en/common.json | 3 +- .../costcenter/public/locales/zh/common.json | 3 +- .../costcenter/src/pages/valuation/index.tsx | 30 +++++++++++++++---- .../src/pages/deploy/components/Form.tsx | 9 ++++-- .../src/pages/deploy/components/Header.tsx | 24 ++++++++++----- .../src/pages/deploy/components/ReadMe.tsx | 6 ++-- .../template/src/pages/deploy/index.tsx | 21 ++++++++----- .../src/pages/develop/components/YamlList.tsx | 6 ++-- .../template/src/pages/develop/index.tsx | 15 ++++++---- .../providers/template/src/pages/index.tsx | 18 +++++++---- .../src/pages/instance/components/dbList.tsx | 9 ++++-- 15 files changed, 128 insertions(+), 78 deletions(-) diff --git a/frontend/packages/driver/src/utils.ts b/frontend/packages/driver/src/utils.ts index 75a8844819c..4b48a48aa8d 100644 --- a/frontend/packages/driver/src/utils.ts +++ b/frontend/packages/driver/src/utils.ts @@ -1,6 +1,11 @@ -import { getConfig } from "./config"; +import { getConfig } from './config'; -export function easeInOutQuad(elapsed: number, initialValue: number, amountOfChange: number, duration: number): number { +export function easeInOutQuad( + elapsed: number, + initialValue: number, + amountOfChange: number, + duration: number +): number { if ((elapsed /= duration / 2) < 1) { return (amountOfChange / 2) * elapsed * elapsed + initialValue; } @@ -12,14 +17,14 @@ export function getFocusableElements(parentEls: Element[] | HTMLElement[]) { 'a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])'; return parentEls - .flatMap(parentEl => { + .flatMap((parentEl) => { const isParentFocusable = parentEl.matches(focusableQuery); const focusableEls: HTMLElement[] = Array.from(parentEl.querySelectorAll(focusableQuery)); return [...(isParentFocusable ? [parentEl as HTMLElement] : []), ...focusableEls]; }) - .filter(el => { - return getComputedStyle(el).pointerEvents !== "none" && isElementVisible(el); + .filter((el) => { + return getComputedStyle(el).pointerEvents !== 'none' && isElementVisible(el); }); } @@ -28,14 +33,14 @@ export function bringInView(element: Element) { return; } - const shouldSmoothScroll = getConfig("smoothScroll"); + const shouldSmoothScroll = getConfig('smoothScroll'); element.scrollIntoView({ // Removing the smooth scrolling for elements which exist inside the scrollable parent // This was causing the highlight to not properly render - behavior: !shouldSmoothScroll || hasScrollableParent(element) ? "auto" : "smooth", - inline: "center", - block: "center", + behavior: !shouldSmoothScroll || hasScrollableParent(element) ? 'auto' : 'smooth', + inline: 'center', + block: 'center' }); } diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment-detail.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment-detail.tsx index 2c89bc64a27..c526aab02a7 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment-detail.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment-detail.tsx @@ -13,7 +13,7 @@ const DeploymentDetail = ({ obj: dep, open, onClose }: DetailDrawerProps ); } + function Valuation() { const { t, i18n } = useTranslation(); const cookie = getCookie('NEXT_LOCALE'); @@ -196,7 +200,7 @@ function Valuation() { {t('Valuation.Standard')} - + {t('common valuation')} @@ -222,9 +226,21 @@ function Valuation() { - - {t(x.title)} - + + + {t(x.title)} + + {x.title === 'Port' && ( + + {t('onlyChargedWhenOpenDBPublicAccess')} + + )} + {[x.unit, x.title !== 'network' ? `${t(CYCLE[cycleIdx])}` : ''] @@ -239,7 +255,7 @@ function Valuation() { {gpuEnabled && gpuData.length > 0 && ( - + {t('Gpu valuation')} @@ -315,7 +331,9 @@ function Valuation() { ); } + export default Valuation; + export async function getServerSideProps(content: any) { const locale = content?.req?.cookies?.NEXT_LOCALE || 'zh'; process.env.NODE_ENV === 'development' && i18n?.reloadResources(locale, undefined); diff --git a/frontend/providers/template/src/pages/deploy/components/Form.tsx b/frontend/providers/template/src/pages/deploy/components/Form.tsx index 60b27634707..f7d61f6ad1f 100644 --- a/frontend/providers/template/src/pages/deploy/components/Form.tsx +++ b/frontend/providers/template/src/pages/deploy/components/Form.tsx @@ -62,7 +62,8 @@ const Form = ({ w="200px" className="template-dynamic-label" color={'#333'} - userSelect={'none'}> + userSelect={'none'} + > {item?.label} {item?.required && ( @@ -92,14 +93,16 @@ const Form = ({ alignItems="center" h={'160px'} w={'100%'} - flexDirection="column"> + flexDirection="column" + > + alignItems={'center'} + > diff --git a/frontend/providers/template/src/pages/deploy/components/Header.tsx b/frontend/providers/template/src/pages/deploy/components/Header.tsx index a8461c9ac9f..ff7a529be19 100644 --- a/frontend/providers/template/src/pages/deploy/components/Header.tsx +++ b/frontend/providers/template/src/pages/deploy/components/Header.tsx @@ -85,7 +85,8 @@ const Header = ({ h={'80px'} borderRadius={'8px'} backgroundColor={'#FBFBFC'} - border={' 1px solid rgba(255, 255, 255, 0.50)'}> + border={' 1px solid rgba(255, 255, 255, 0.50)'} + > @@ -102,7 +103,8 @@ const Header = ({ _hover={{ background: '#F4F6F8' }} - onClick={(e) => goGithub(e, templateDetail?.spec?.gitRepo)}> + onClick={(e) => goGithub(e, templateDetail?.spec?.gitRepo)} + > {t('Home Page')} @@ -119,7 +121,8 @@ const Header = ({ alignItems={'center'} _hover={{ background: '#F4F6F8' - }}> + }} + > {t('Share')} @@ -134,7 +137,8 @@ const Header = ({ w="60px" flexDirection={'column'} justifyContent={'center'} - alignItems={'center'}> + alignItems={'center'} + > @@ -150,7 +154,8 @@ const Header = ({ copyData(HtmlPart)}> + onClick={() => copyData(HtmlPart)} + > @@ -162,7 +167,8 @@ const Header = ({ flexDirection={'column'} alignItems={'center'} ml="auto" - onClick={() => copyData(MdPart)}> + onClick={() => copyData(MdPart)} + > @@ -189,7 +195,8 @@ const Header = ({ fontSize={'12px'} color={'5A646E'} fontWeight={400} - onClick={() => copyData(templateDetail?.spec?.description)}> + onClick={() => copyData(templateDetail?.spec?.description)} + > {templateDetail?.spec?.description} @@ -204,7 +211,8 @@ const Header = ({ bg={'myWhite.600'} borderColor={'myGray.200'} variant={'base'} - onClick={handleExportYaml}> + onClick={handleExportYaml} + > {t('Export')} Yaml diff --git a/frontend/providers/template/src/pages/index.tsx b/frontend/providers/template/src/pages/index.tsx index 690477510a4..999368d5126 100644 --- a/frontend/providers/template/src/pages/index.tsx +++ b/frontend/providers/template/src/pages/index.tsx @@ -73,13 +73,15 @@ export default function AppList() { borderRadius={'12px'} background={'linear-gradient(180deg, #FFF 0%, rgba(255, 255, 255, 0.70) 100%)'} py={'36px'} - px="42px"> + px="42px" + > + minW={'765px'} + > {filterData && filterData?.map((item: TemplateType) => { return ( @@ -99,7 +101,8 @@ export default function AppList() { borderRadius={'8px'} backgroundColor={'#fff'} boxShadow={'0px 2px 4px 0px rgba(187, 196, 206, 0.25)'} - border={'1px solid #EAEBF0'}> + border={'1px solid #EAEBF0'} + > + border={' 1px solid rgba(255, 255, 255, 0.50)'} + > @@ -127,7 +131,8 @@ export default function AppList() { mt={'8px'} fontSize={'12px'} color={'5A646E'} - fontWeight={400}> + fontWeight={400} + > {item?.spec?.description} @@ -143,7 +148,8 @@ export default function AppList() { fill="#5A646E" _hover={{ fill: '#0884DD' - }}> + }} + > diff --git a/frontend/providers/template/src/pages/instance/components/dbList.tsx b/frontend/providers/template/src/pages/instance/components/dbList.tsx index 5e23732c78e..4391422d8ad 100644 --- a/frontend/providers/template/src/pages/instance/components/dbList.tsx +++ b/frontend/providers/template/src/pages/instance/components/dbList.tsx @@ -98,7 +98,8 @@ export default function AppList({ instanceName }: { instanceName: string }) { variant={'base'} leftIcon={} px={3} - onClick={() => handleToDetailPage(item.name)}> + onClick={() => handleToDetailPage(item.name)} + > {t('Details')} @@ -129,14 +130,16 @@ export default function AppList({ instanceName }: { instanceName: string }) { justifyContent={'center'} alignItems={'center'} background={'white'} - p="32px"> + p="32px" + > + alignItems={'center'} + > From b9418ed6b7ece3977ba078cd37a11926cf0c59b0 Mon Sep 17 00:00:00 2001 From: xudaotutou <13435638964@163.com> Date: Fri, 22 Dec 2023 14:38:08 +0800 Subject: [PATCH 12/38] fix(object-storage):preview & copyURL (#4444) --- frontend/providers/objectstorage/README.md | 39 ------------------- .../BucketContainer/FileManager.tsx | 26 +++++++++++-- 2 files changed, 22 insertions(+), 43 deletions(-) diff --git a/frontend/providers/objectstorage/README.md b/frontend/providers/objectstorage/README.md index a75ac524881..8b137891791 100644 --- a/frontend/providers/objectstorage/README.md +++ b/frontend/providers/objectstorage/README.md @@ -1,40 +1 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. - -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. - -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/frontend/providers/objectstorage/src/components/BucketContainer/FileManager.tsx b/frontend/providers/objectstorage/src/components/BucketContainer/FileManager.tsx index 0e220ded981..2778709c10a 100644 --- a/frontend/providers/objectstorage/src/components/BucketContainer/FileManager.tsx +++ b/frontend/providers/objectstorage/src/components/BucketContainer/FileManager.tsx @@ -1,5 +1,5 @@ import { deleteObject, listObjects } from '@/api/s3'; -import { FolderPlaceholder, QueryKey } from '@/consts'; +import { Authority, FolderPlaceholder, QueryKey } from '@/consts'; import { useOssStore } from '@/store/ossStore'; import { AbsoluteCenter, @@ -42,7 +42,7 @@ import VisibityIcon from '../Icons/VisibilityIcon'; import LinkIcon from '../Icons/LinkIcon'; import FileIcon from '../Icons/FileIcon'; import FolderIcon from '../Icons/FolderIcon'; -import { GetObjectCommand, _Object } from '@aws-sdk/client-s3'; +import { GetObjectCommand, S3, S3Client } from '@aws-sdk/client-s3'; import { useToast } from '@/hooks/useToast'; import { useEffect, useState } from 'react'; import ArrowDownSLineIcon from '../Icons/ArrowDownSLineIcon'; @@ -205,6 +205,23 @@ export default function FileManager({ ...styles }: FlexProps) { isDir: true }); const fuseList = fuse.search(searchVal); + // get url + const generateUrl = async (client: S3, Bucket: string, Key: string) => { + if (bucket?.policy === Authority.private) { + return getSignedUrl( + client, + new GetObjectCommand({ + Bucket, + Key + }) + ); + } else { + const ep = await client.config.endpoint!(); + const { protocol, hostname, path } = ep; + const url = `${protocol}//${hostname}${path}${Bucket}/${Key}`; + return url; + } + }; // -------- // budle delete const deleteCheckBoxGroupState = useCheckboxGroup({ @@ -243,6 +260,7 @@ export default function FileManager({ ...styles }: FlexProps) { }); deleteCheckBoxGroupState.setValue([]); }; + const trueFileList = fileList.filter( (f) => !((f.fileName === '..' && f.isDir) || f.fileName === FolderPlaceholder) ); @@ -409,7 +427,7 @@ export default function FileManager({ ...styles }: FlexProps) { onClick={(e) => { e.stopPropagation(); if (!s3client || !Bucket) return; - getSignedUrl(s3client, new GetObjectCommand({ Bucket, Key: file.Key })) + generateUrl(s3client, Bucket, file.Key) .then((url) => { window.open(new URL(url)); }) @@ -430,7 +448,7 @@ export default function FileManager({ ...styles }: FlexProps) { onClick={(e) => { e.stopPropagation(); if (!s3client || !Bucket) return; - getSignedUrl(s3client, new GetObjectCommand({ Bucket, Key: file.Key })) + generateUrl(s3client, Bucket, file.Key) .then((url) => { copyData(url); }) From 967c5bf77d3515857074f34619289316a7d23884 Mon Sep 17 00:00:00 2001 From: sealos-release-robot Date: Sat, 23 Dec 2023 10:06:27 +0800 Subject: [PATCH 13/38] =?UTF-8?q?=F0=9F=A4=96=20add=20release=20changelog?= =?UTF-8?q?=20using=20rebot.=20(#4442)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: sealos-release-robot --- CHANGELOG/CHANGELOG-5.0.0-beta4.md | 144 +++++++++++++++++++++++++++++ CHANGELOG/CHANGELOG.md | 1 + 2 files changed, 145 insertions(+) create mode 100644 CHANGELOG/CHANGELOG-5.0.0-beta4.md diff --git a/CHANGELOG/CHANGELOG-5.0.0-beta4.md b/CHANGELOG/CHANGELOG-5.0.0-beta4.md new file mode 100644 index 00000000000..96d42c087c7 --- /dev/null +++ b/CHANGELOG/CHANGELOG-5.0.0-beta4.md @@ -0,0 +1,144 @@ +Welcome to the v5.0.0-beta4 release of Sealos!🎉🎉! + + + +## Changelog +### New Features +* dc998b5b2d4d7c8046bfc88fee543e077078aff7: feat(costcenter): pinning table (#4343) (@xudaotutou) +* 7c08451b7461ab4e39f4a42ef4fe846d3acbc56b: feat(desktop): signup api (#4314) (@xudaotutou) +* e84a782111563c803ad07e386245dd47a8373cc9: feat: Replaced mobx with zustand (#4358) (@Wishrem) +* 5330a703060ddfa4211da56b0b56384724cd3f66: feat: accomplished create, update and delete function in Kube Panel (#4300) (@Wishrem) +* 80c948a10bbcc846c42e0f2aa81b9e567762a7bc: feat: add heartbeat for sealos self-host cluster. (#4389) (@lingdie) +* 3eb68232381e705167e7ccdf273eb99db237b9bb: feat: message notification (#4350) (@bxy4543) +* a04ca534543a48f29c9978cc7fb24622472c5de5: feat: release KubePanel v1.0.0 (#4401) (@Wishrem) +* 5c5903031299a2cda106ba800c2c4c68450f872f: feat:app launchpad && template supports api calls (#4322) (@zjy365) +* 33c7084e6d5e6b998700c01969d6c3d01f3a8291: feat:control file migration and template sharing link (#4421) (@zjy365) +* f9f2d61dc114545939457d56ee63859482bc120d: feat:db add database type for migration and external network access (#4317) (@zjy365) +* 552dac8a5ce53df4dd36a4743e4fce9224a1e11a: feat:db add kafka monitor (#4359) (@zjy365) +* d518f580cc6f1a25b8fcbbfad8a057b57aea38dc: feat:db automatic database backup (#4377) (@zjy365) +* b6654c4010a00ddff88a8ed5f8061ecb6405ea56: feat:db delete some databases (#4379) (@zjy365) +* 9bb66ebdfc6fab741cc6eff833df145f37c5eb62: feat:db modify deployment env (#4345) (@zjy365) +* 174f08fb9372c622eaae47870dec1c33134f1599: feat:desktop & applaunchpad novice guide (#4392) (@zjy365) +* bf5379f6d98047eb7b915a6c56c0acc33eb0f3c5: feat:desktop notification (#4371) (@zjy365) +* fc0c3f6f9173614deaa0593f32c5101d0782da65: feat:docs add blog (#4298) (@zjy365) +* 98dbeb49890673e878914c055d3ff1b27945fb17: feat:docs add head meta (#4260) (@zjy365) +* fdbccd6d46c136b1a83cde4b36eddf760ab3c06b: feat:docs add link proxy (#4266) (@zjy365) +* 27b000c83103a2d7d835c8cc5b97ef4a04151a01: feat:docs banner (#4415) (@zjy365) +* ad77db0e9218ec9517334820b853af658edbabb1: feat:docs robots.txt (#4406) (@zjy365) +* 7a8fffa42983334936ff9aa8aa67c13b22da2449: feat:frontend new api call && database file migration (#4332) (@zjy365) +* 94ac016d8bdff38559ed75d4d158791643fcb4c2: feat:implement license id scheme (#4413) (@zjy365) +* 8069caa36bab6b6dcbeced52f73d2895cfc3612c: feat:launchpad jsonpatch & template add filename (#4436) (@zjy365) +* 2255850717bf5b202c490f6d4ccd63cadc0b3520: feat:launchpad support multiple containers (#4380) (@zjy365) +* 675700b3593f667f96b020f9e5f49685b2cb2399: feat:license deploy tutorial & monorepo dependencies (#4274) (@zjy365) +* 7fd40c2480abf8200ca243c44d7da8191efa3a99: feat:license deployment command (#4316) (@zjy365) +### Bug fixes +* 48f9c4b83a05579e9f5e1fadcf4441ff7c165577: bugfix: fix sudo -E '' with an helm cmd has single quotation (#4427) (@daymade) +* f52b1743797c5ce76d97c9efaa2bdfb77ac74903: feat & fix: Event, Ingress and Secret Overview & Errors in using next build (#4374) (@Wishrem) +* 56772da875f21b408d7edcf043daef8a75c97698: fix(objectstorage): regex (#4296) (@xudaotutou) +* 19340f5378b28bf31ed70bd0667a9587abbc7e07: fix(template): laf template (#4351) (@xudaotutou) +* cf3041dc0c1a804bb4b39777910edc19149a6254: fix(template):fix deps, fix styles (#4378) (@xudaotutou) +* fd55bac31490d6f0e87404607a223a51d8da676f: fix: Display of UI and functional integration in Kube Panel (#4365) (@Wishrem) +* a5be5cb7909d0728e18d3d2faf3feaf0c3e7aea4: fix: activator logic. (#4430) (@lingdie) +* 333f05d2aaf2953391fa47a95765065da70e00c8: fix: admission for ingress delete (#4327) (@lingdie) +* 10ec57654023336dc98145e8a5ba07faf114fc80: fix: cloud release ci (#4336) (@lingdie) +* 9c9c9d74f75c371c9a3b2491a9c2c68c4a39261c: fix: desktop rbac for delete request of user. (#4308) (@lingdie) +* cb35d788bdcff0b3558c5ebbc9a8c55b442b85dd: fix: document seo optimization (#4372) (@zjy365) +* c39bd8931dc9414e0221bb14acd8b9a970b55e8a: fix: launchpad rollingupdate (#4285) (@c121914yu) +* 6fc583a87dbc91e54cd23712c4be5383c36001bd: fix: return cors anno as nil if port is 443. (#4356) (@lingdie) +* 2a418813d2fa3bcb644cc209f6315424708feca2: fix: skip vingress when delete ingress. (#4318) (@lingdie) +* 56123b852c7f87b4e7bf54df81f031029d12b594: fix:adapt to desktop open template (#4398) (@zjy365) +* 9466c122041b4c5d6a65bde2a806fcdd53202508: fix:app statefulset & template develop (#4363) (@zjy365) +* d2e6d78b4fcad85a8952237c73249236219f0e96: fix:db service labels (#4344) (@zjy365) +* 18aff5d84a6679b5ecba5a2bbc358e633b9869b2: fix:deploy menuData helpDocs (#4437) (@zjy365) +* 258e565628c27099430df5f4c55424c4b53b7039: fix:desktop usedriver & tempalte yml (#4432) (@zjy365) +* 3c8db86965ca9ee43d504027291b6999190fc52c: fix:docs & delete db role & baidu (#4272) (@zjy365) +* fa3f041cdb7bc92e7ad0fdfcb00f9dc8974ad7ba: fix:docs banner path (#4303) (@zjy365) +* ce5966d7a06d59e21c6d4ef30c75c795e7ec7e8e: fix:docs head meta (#4262) (@zjy365) +* c0492a1e98b8dbb6faa23e3d252892c20ef5d830: fix:docs router path (#4292) (@zjy365) +* 17fe9c2648dd2c9227e3d411434c8a532f7903ca: fix:frontend upload convertdata (#4382) (@zjy365) +* 4c166d3140f00eff8ecc3044768b24088d5c81bc: fix:launchpad issuer and certificates (#4405) (@zjy365) +* b9a7ed74a4b0672139abec44f81f8e39684d84eb: fix:tempalte detail api add cdn (#4428) (@zjy365) +### Other work +* 520c69ded6fb6aacc2423f58fd6bb03be3180942: Add Object Storage (#4333) (@nowinkeyy) +* 72852aa836f3a02003e96f15403e46c97757be65: Add database config docs (#4414) (@wallyxjh) +* 67dd44e0c971df567418db5eeebe7dcaf63898ed: Add post "k8s-multi-tenancy" (#4364) (@yangchuansheng) +* e6a9868cd04b9bb5dd2ab81fe0e6402218a86237: Bump: add sub go works to support bump kubernetes api from v0.25.6 to v0.27.4 or higher. (#4281) (@lingdie) +* e8610d68842c9c9799f9ccac4af519139af4da46: CI: add cloud release ci and use ossutil to upload offline tar package. (#4265) (@lingdie) +* a3efc3a93d1223f0f4083db37c5b201624165d65: Chore: upgrade and fix cloud build logic (#4408) (@lingdie) +* 4efa9d802e426ff282fd2b063860ac9f50ea3d4e: Delete useless code (#4340) (@bxy4543) +* bd68a735b4af26839bc98636a8da166ac8812998: Depre Bytebase and imagehub. (#4273) (@zzjin) +* 30fa9e2e7316946d5b7c96f705f83a5ce5f5b2f7: Depre copilot4prs. (#4418) (@zzjin) +* 60cf98e4049b198e0e73c10e4d09fbf42c828316: Docs: add blog "To run or not to run a database on Kubernetes" (#4385) (@yangchuansheng) +* c3f5bf6bacdbf1987943888f0e09c5823e410002: Docs: add docs for app launchpad (#4411) (@yangchuansheng) +* f1a78a5a2bd48137bb5c5981b4309a234689d3e9: Docs: add environment for building website (#4267) (@yangchuansheng) +* 78543a30dca9bebde3c055946a66f6d4d455c37e: Docs: add post "what is sealos" (#4313) (@yangchuansheng) +* 195165fc7e17f395dfa9e454ad054542dd143229: Docs: add post (#4309) (@yangchuansheng) +* a3412cd822beee24c80b484b11b154f7c4e46fa3: Docs: fix bug for building documentation site (#4310) (@yangchuansheng) +* 999816eea84021cf1167f0f36d5895657ca34d8e: Docs: update Q&A document (#4305) (@yangchuansheng) +* e405276f6ed2a462899e671d9240e0642090cb43: Docs: update README (#4321) (@yangchuansheng) +* 2fed810be6ad4aa9927dcb9ee5677773170f1b56: Docs: update documentation for deploying k8s & sealos (#4367) (@yangchuansheng) +* 88ef18f0124f52add5d86c5393835b087a097239: Docs: update installation (#4261) (@yangchuansheng) +* 4bea4eaf3654e40e68101c4646b3a05d89367592: Feat/cost service (#4391) (@bxy4543) +* 5312580d3f73660accc4121cae93c81330dd5c2a: Feat/gift balance (#4390) (@bxy4543) +* 05e8baf8ab8a40432c7e6c3b75ef3011eb67b81c: Feat/minio cost (#4339) (@bxy4543) +* c9527a7f77ddba8966865838ee5dca000ea6c89c: Fix acme service type. (#4403) (@zzjin) +* 5d8e6706de305db006dbdea2e14ddc6da9a7024a: Fix desktop and use icons from packages instead of public (#4307) (@xudaotutou) +* 2113d17e5ae2f5fec74b2d114495767aefdfcb2e: Fix env for BD_TOKEN (#4268) (@yangchuansheng) +* bfe029c1c22a330835138ef704580954462c58c9: Fix higress annotation. (#4326) (@zzjin) +* 55b4807999e2e03fbc58203a7672635d0dd51666: Fix template deploy ingress temp. (#4234) (@zzjin) +* e82b92f3635edf2584837c8912ead3052f76b61d: Fix vingress (#4319) (@lingdie) +* c4e8187ec073c2c256a2ced74ce03a488bdf5d36: Fix/cloud port (#4271) (@bxy4543) +* 3677c36299d7418fc9c8fff065fc39cfbaf5e1d4: Optimize/remote cmd return error (#4407) (@bxy4543) +* e94d709e718d0651a8c7313a88cfbf784cad9a73: Pref: sealos self-hosting docs. (#4299) (@lingdie) +* edde8600eefc0a23db1a39b9407a13cbe48da797: Update Quick installation of Vue Apps.md (#4434) (@alili) +* 3963a1abf9da541aa5ee2f57137b62cccec3eb22: Update db docs (#4381) (@wallyxjh) +* 9095a2eda2ae8fa87e6e4bd31869f9624230e26f: Update gateway usage (#4264) (@zzjin) +* 881e165d8418d43f57317c0494d56067c961e46b: Update git clone command for template provider. (#4315) (@zzjin) +* 86c2f8fb922eadc7bfedb344015571435b9a817f: Update private cloud link (#4257) (@fanux) +* 40e33e0d956ffed2f4024babbf82bd47061dbe32: add cluster id for license controller. (#4237) (@lingdie) +* ba71f1ded49aab6ff6aaa1f2b0dd8bdaffcffa16: add kafka monitor (#4349) (@wallyxjh) +* b15d62fae53ab392857d661897881872f1a799fc: add suspend os and resume os (#4354) (@nowinkeyy) +* 38ec5da3b7b1b2bbd4f0f4018f1d34f5ab2753e2: change nodeport default price (#4429) (@bxy4543) +* e84c9e39a6a50fb804a0c3d7c510b404f75a0020: chroe: add template cluster image for sealos cloud upgrad. (#4388) (@lingdie) +* 4ef6bb6b934d16f197eea4b795338c9a5140c601: ci: fix sealos cli in cloud release ci. (#4338) (@lingdie) +* bd52c56fe40d045939728faf740523bd7507f059: ci: skip objectstorage ci. (#4329) (@lingdie) +* ac9bd5ec0b2846e0e9ec5c71d1a06a08cf204da8: debt skip license cr. (#4275) (@bxy4543) +* b56174b827cb23b967a492e30380c99aeb0fef68: docs: Automated Changelog Update for v4.4.0-beta3 (#4290) (@sealos-release-robot) +* 94c702ecc3dd7722fe8c0a2f38bda6408d8ead22: docs: add workspace usage doc. (#4368) (@lingdie) +* f21b7c91a46eaee509438fea13662cebf14398eb: docs: upgrade sreg gomod (#4263) (@LZiHaN) +* 0429b0dbdbecb4868952e1cde5b4ab03a5b0396f: docs:support lang env (#4288) (@zjy365) +* 46127eca157b4ae851ce60a500e7a8e6be884c24: feat(frontend/minio): minio provider (#4295) (@xudaotutou) +* a2f3ca09f90f23a9aff5985a208d37a2f8a80bc9: feat. ingress mutate webhook support annotations flags. (#4293) (@lingdie) +* 37709ce8db4ac9db65a241d12d66faee84e54cbe: fix & style: tailwind css conflict and UI problem & clean some codes (#4416) (@Wishrem) +* 6d71ab2e842915ccd0e520f8b75e92270223c724: fix get monitoring result (#4242) (@bxy4543) +* edc5ccb66e8911096a0105874239a500cc413cc0: fix go work (#4289) (@nowinkeyy) +* 7a312773a4a8710abeed3b70a4841cfd1c3873cc: fix license (#4412) (@lingdie) +* 4a67761a440078b762a70e78f888656dd35195d9: fix monitor bug (#4352) (@nowinkeyy) +* e649c51b550a88b81035d06f40b2cf1edc6e81d8: fix monitor object storage (#4362) (@bxy4543) +* 4dedc10ee1f26ca55ff817edc3bc5b398a18335a: fix notification read status (#4369) (@bxy4543) +* 30b47a8bc121a97f358bad18c6c7c1640cf75e4c: fix os endpoint error (#4357) (@nowinkeyy) +* 77fdddcb53abfa1a2c40fa62824a9b3e7c49292f: fix sync error (#4342) (@nowinkeyy) +* 0af9b054f151b6977f71694d8bbc49386a7a4112: fix template readme img src (#4426) (@zjy365) +* d705eb523ca9745db8bd6d8556771299ffce4bfa: fix tmpl cloud port (#4335) (@bxy4543) +* ea37dc9e037ac6b5821ad532ba99fce1b9703819: fix(costcenter: invoice) (#4294) (@xudaotutou) +* 6405d93ee32df974725d969cfefad61301aa1f46: fix(object-storage): switch kc (#4355) (@xudaotutou) +* b6643a466499eaf98c90715876dd1657b98cde60: pref: offline tar support arm64. (#4306) (@lingdie) +* 87a14ea1ab44a21d5fd7a9c2b727d3f31560a1fa: pref: sealos self-hosting qa docs. (#4302) (@lingdie) +* c6c1b58b0f2eef2ad95c5a52a415a99a535130c4: refactor(costcenter): refactor bonus (#4384) (@xudaotutou) +* 5893b55b11a8cf71851e0fcdab9ef150a64d5664: refactor(main): upgrade api v1.27.4 support v1.28+ (#4394) (@cuisongliu) +* f2fef17fce042f3f8c34bd004c5f05c197538ab5: remove switch language annotation (#4393) (@zjy365) +* d82232340fc333ce22a4864834a9aac24fd78c7b: style: rename the plugin from Monitor to Kube Panel and update UI style (#4269) (@Wishrem) +* 160b7a2567a13e333f78789f9aa5aba6b840c9a6: styles(desktop): update desktop worksapce (#4328) (@xudaotutou) +* f72c2954629e395e3fb6277b0066bfedb0addb6a: typo: fix secret name in qa. (#4353) (@lingdie) +* 5718956efc3bc615c7156af9df4ddbe2bf6ef024: update dbprovider docs (#4325) (@wallyxjh) +* 9b2fc94952680adc1f2b8c21406f50d48129485b: update kafka monitor (#4361) (@wallyxjh) +* ce57c323eb675379ea1f7008e187cfb27b6bfe55: update rbac and fix minio user not exist error (#4366) (@nowinkeyy) +* 6d8e1f5128b5e3c20fbda78a0e8f9d5a169571dc: 🤖 add release changelog using rebot. (#4256) (@sealos-release-robot) + +**Full Changelog**: https://github.com/labring/sealos/compare/v5.0.0-beta3...v5.0.0-beta4 + +See [the CHANGELOG](https://github.com/labring/sealos/blob/main/CHANGELOG/CHANGELOG.md) for more details. + +Your patronage towards Sealos is greatly appreciated 🎉🎉. + +If you encounter any problems during its usage, please create an issue in the [GitHub repository](https://github.com/labring/sealos), we're committed to resolving your problem as soon as possible. diff --git a/CHANGELOG/CHANGELOG.md b/CHANGELOG/CHANGELOG.md index 0165f15f852..82946aa3c5c 100644 --- a/CHANGELOG/CHANGELOG.md +++ b/CHANGELOG/CHANGELOG.md @@ -2,6 +2,7 @@ All notable changes to this project will be documented in this file. +- [CHANGELOG-5.0.0-beta4.md](./CHANGELOG-5.0.0-beta4.md) - [CHANGELOG-5.0.0-beta3.md](./CHANGELOG-5.0.0-beta3.md) - [CHANGELOG-5.0.0-beta2.md](./CHANGELOG-5.0.0-beta2.md) - [CHANGELOG-5.0.0-beta1.md](./CHANGELOG-5.0.0-beta1.md) From 8abdf56a684331ed2fc7c754a9f34290f6c3f9a4 Mon Sep 17 00:00:00 2001 From: Zihan Li Date: Sat, 23 Dec 2023 10:07:04 +0800 Subject: [PATCH 14/38] feat(sealos create): Add command preview functionality (#4291) * feat: add command preview functionality * move formalizeWorkingCommand into guest pkg * add license * update: ImageType var --- pkg/buildah/create.go | 27 ++++++++ pkg/guest/guest.go | 21 +----- pkg/guest/util.go | 37 +++++++++++ service/go.work.sum | 145 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 212 insertions(+), 18 deletions(-) create mode 100644 pkg/guest/util.go diff --git a/pkg/buildah/create.go b/pkg/buildah/create.go index d07c2a6d68b..170718df915 100644 --- a/pkg/buildah/create.go +++ b/pkg/buildah/create.go @@ -19,6 +19,14 @@ import ( "fmt" "os" "os/exec" + "strings" + + "github.com/labring/sealos/pkg/guest" + + "github.com/containers/buildah" + + "github.com/labring/sealos/fork/golang/expansion" + v2 "github.com/labring/sealos/pkg/types/v1beta1" stringsutil "github.com/labring/sealos/pkg/utils/strings" @@ -86,6 +94,7 @@ func newCreateCmd() *cobra.Command { } if !opts.short { + printCommands(opts.name, opts.env, info) logger.Info("Mount point: %s", info.MountPoint) } else { fmt.Println(info.MountPoint) @@ -140,3 +149,21 @@ func runRender(mountPoints []string, env []string) error { return eg.Wait() } + +func printCommands(name string, env []string, info buildah.BuilderInfo) { + envs := maps.Merge(maps.FromSlice(info.OCIv1.Config.Env), maps.FromSlice(env)) + mapping := expansion.MappingFuncFor(envs) + + typeKey := maps.GetFromKeys(info.OCIv1.Config.Labels, v2.ImageTypeKeys...) + + cmds := make([]string, 0) + for i := range info.OCIv1.Config.Entrypoint { + cmds = append(cmds, guest.FormalizeWorkingCommand(name, info.Container, v2.ImageType(typeKey), expansion.Expand(info.OCIv1.Config.Entrypoint[i], mapping))) + } + + for i := range info.OCIv1.Config.Cmd { + cmds = append(cmds, guest.FormalizeWorkingCommand(name, info.Container, v2.ImageType(typeKey), expansion.Expand(info.OCIv1.Config.Cmd[i], mapping))) + } + + logger.Info("Shell command: %s", stringsutil.RenderShellWithEnv(strings.Join(cmds, "; "), envs)) +} diff --git a/pkg/guest/guest.go b/pkg/guest/guest.go index 03c22311fa5..3a76372e4f3 100644 --- a/pkg/guest/guest.go +++ b/pkg/guest/guest.go @@ -16,13 +16,11 @@ package guest import ( "context" - "fmt" "strings" "golang.org/x/sync/errgroup" "github.com/labring/sealos/fork/golang/expansion" - "github.com/labring/sealos/pkg/constants" "github.com/labring/sealos/pkg/env" "github.com/labring/sealos/pkg/exec" "github.com/labring/sealos/pkg/ssh" @@ -81,19 +79,6 @@ func (d *Default) Apply(cluster *v2.Cluster, mounts []v2.MountImage, targetHosts return nil } -func formalizeWorkingCommand(clusterName string, imageName string, t v2.ImageType, cmd string) string { - if cmd == "" { - return "" - } - switch t { - case v2.RootfsImage, v2.PatchImage: - return fmt.Sprintf(constants.CdAndExecCmd, constants.GetRootWorkDir(clusterName), cmd) - case v2.AppImage, "": - return fmt.Sprintf(constants.CdAndExecCmd, constants.GetAppWorkDir(clusterName, imageName), cmd) - } - return "" -} - func formalizeImageCommands(cluster *v2.Cluster, index int, m v2.MountImage, extraEnvs map[string]string) []string { envs := maps.Merge(m.Env, extraEnvs) envs = v2.MergeEnvWithBuiltinKeys(envs, m) @@ -101,15 +86,15 @@ func formalizeImageCommands(cluster *v2.Cluster, index int, m v2.MountImage, ext cmds := make([]string, 0) for i := range m.Entrypoint { - cmds = append(cmds, formalizeWorkingCommand(cluster.Name, m.Name, m.Type, expansion.Expand(m.Entrypoint[i], mapping))) + cmds = append(cmds, FormalizeWorkingCommand(cluster.Name, m.Name, m.Type, expansion.Expand(m.Entrypoint[i], mapping))) } if index == 0 && len(cluster.Spec.Command) > 0 { for i := range cluster.Spec.Command { - cmds = append(cmds, formalizeWorkingCommand(cluster.Name, m.Name, m.Type, expansion.Expand(cluster.Spec.Command[i], mapping))) + cmds = append(cmds, FormalizeWorkingCommand(cluster.Name, m.Name, m.Type, expansion.Expand(cluster.Spec.Command[i], mapping))) } } else { for i := range m.Cmd { - cmds = append(cmds, formalizeWorkingCommand(cluster.Name, m.Name, m.Type, expansion.Expand(m.Cmd[i], mapping))) + cmds = append(cmds, FormalizeWorkingCommand(cluster.Name, m.Name, m.Type, expansion.Expand(m.Cmd[i], mapping))) } } diff --git a/pkg/guest/util.go b/pkg/guest/util.go new file mode 100644 index 00000000000..af7ba31242f --- /dev/null +++ b/pkg/guest/util.go @@ -0,0 +1,37 @@ +/* +Copyright 2023 cuisongliu@qq.com. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package guest + +import ( + "fmt" + + "github.com/labring/sealos/pkg/constants" + "github.com/labring/sealos/pkg/types/v1beta1" +) + +func FormalizeWorkingCommand(clusterName string, imageName string, t v1beta1.ImageType, cmd string) string { + if cmd == "" { + return "" + } + switch t { + case v1beta1.RootfsImage, v1beta1.PatchImage: + return fmt.Sprintf(constants.CdAndExecCmd, constants.GetRootWorkDir(clusterName), cmd) + case v1beta1.AppImage, "": + return fmt.Sprintf(constants.CdAndExecCmd, constants.GetAppWorkDir(clusterName, imageName), cmd) + } + return "" +} diff --git a/service/go.work.sum b/service/go.work.sum index dcd6740315e..67be41203aa 100644 --- a/service/go.work.sum +++ b/service/go.work.sum @@ -1,45 +1,93 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8= +cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= cloud.google.com/go/compute/metadata v0.2.0 h1:nBbNSZyDpkNlo3DepaaLKVuO7ClyifSAmNloSCZrHnQ= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM= +github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/hcsshim v0.12.0-rc.0 h1:wX/F5huJxH9APBkhKSEAqaiZsuBvbbDnyBROZAqsSaY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 h1:iC9YFYKDGEy3n/FtqJnOkZsene9olVspKmkX5A2YBEo= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.5 h1:yyolbgHfV2Tp91vMjO/CF5aOxKG+UgdVAeUoloEQI3E= +github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 h1:NqugFkGxx1TXSh/pBcU00Y6bljgDPaFdh5MUSeJ7e50= +github.com/alibabacloud-go/dysmsapi-20170525/v3 v3.0.6 h1:UTl97mt2qfavxveqCkaVg4tKaZUPzA9RKbFIRaIdtdg= +github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q= +github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY= +github.com/alibabacloud-go/tea v1.2.1 h1:rFF1LnrAdhaiPmKwH5xwYOKlMh66CqRwPUTzIK74ask= +github.com/alibabacloud-go/tea-utils v1.3.1 h1:iWQeRzRheqCMuiF3+XkfybB3kTgUXkXX+JMrqfLeB2I= +github.com/alibabacloud-go/tea-utils/v2 v2.0.4 h1:SoFgjJuO7pze88j9RBJNbKb7AgTS52O+J5ITxc00lCs= +github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0= +github.com/aliyun/credentials-go v1.3.1 h1:uq/0v7kWrxmoLGpqjx7vtQ/s03f0zR//0br/xWDTE28= github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k= +github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E= github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= +github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= +github.com/containerd/containerd v1.7.0 h1:G/ZQr3gMZs6ZT0qPUZ15znx5QSdQdASW11nXTLTM2Pg= +github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containers/storage v1.50.2 h1:Fys4BjFUVNRBEXlO70hFI48VW4EXsgnGisTpk9tTMsE= github.com/containers/storage v1.50.2/go.mod h1:dpspZsUrcKD8SpTofvKWhwPDHD0MkO4Q7VE+oYdWkiA= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= @@ -52,21 +100,32 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0 h1:dulLQAYQFYtG5MTplgNGHWuV2D+OBD+Z8lmDBmbLg+s= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/flowstack/go-jsonschema v0.1.1 h1:dCrjGJRXIlbDsLAgTJZTjhwUJnnxVWl1OgNyYh5nyDc= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8= @@ -85,25 +144,39 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/cel-go v0.12.6 h1:kjeKudqV0OygrAqA9fX6J55S8gj+Jre2tckIm5RoG4M= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220517205856-0058ec4f073c h1:rwmN+hgiyp8QyBqzdEX43lTjKAxaqCrYHaU5op5P9J8= github.com/ianlancetaylor/demangle v0.0.0-20220517205856-0058ec4f073c/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -111,71 +184,131 @@ github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= +github.com/labring/operator-sdk v1.0.1 h1:JS+j9nF0lihkPJnMYJBZrH7Kfp/dKB2cnbBRMfkmE+g= +github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE= github.com/matoous/go-nanoid v1.5.0 h1:VRorl6uCngneC4oUQqOYtO3S0H5QKFtKuKycFG3euek= +github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/minio/madmin-go/v3 v3.0.35 h1:cCo5ZZpHA+rlBQbsAcwFwiuh/uHJmjVoDDx1G4+zaho= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.64 h1:Zdza8HwOzkld0ZG/og50w56fKi6AAyfqfifmasD9n2Q= github.com/minio/minio-go/v7 v7.0.64/go.mod h1:R4WVUR6ZTedlCcGwZRauLMIKjgyaWxhs4Mqi/OMPmEc= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= +github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/mrunalp/fileutils v0.5.0 h1:NKzVxiH7eSk+OQ4M+ZYW1K6h27RUV3MI6NUTsHhU6Z4= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM= github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= github.com/opencontainers/runc v1.1.9/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/prom2json v1.3.3 h1:IYfSMiZ7sSOfliBoo89PcufjWO4eAR0gznGcETyaUgo= github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 h1:RpforrEYXWkmGwJHIGnLZ3tTWStkjVVstwzNGqxX2Ds= +github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc= +github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= +github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= +github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= +go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg= +go.etcd.io/etcd/client/v2 v2.305.7 h1:AELPkjNR3/igjbO7CjyF1fPuVPjrblliiKj+Y6xSGOU= +go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4= +go.etcd.io/etcd/pkg/v3 v3.5.7 h1:obOzeVwerFwZ9trMWapU/VjDcYUJb5OfgC1zqEGWO/0= +go.etcd.io/etcd/raft/v3 v3.5.7 h1:aN79qxLmV3SvIq84aNTliYGmjwsW6NqJSnqmI1HLJKc= +go.etcd.io/etcd/server/v3 v3.5.7 h1:BTBD8IJUV7YFgsczZMHhMTS67XuA4KpRquL0MFOJGRk= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 h1:xFSRQBbXF6VvYRf2lqMJXxoB72XI1K/azav8TekHHSw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 h1:sxoY9kG1s1WpSYNyzm24rlwH4lnRYFXUVVBmKMBfRgw= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 h1:TaB+1rQhddO1sF71MpZOZAuSPW1klK2M8XxfrBMfK7Y= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 h1:pDDYmo0QadUPal5fwXoY1pmMpFcdyhXOmL5drCrI3vU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 h1:KtiUEhQmj/Pa874bVYKGNVdq8NPKiacPbaRRtgXi+t4= +go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= +go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4 h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0= @@ -224,6 +357,7 @@ golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.3.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -234,6 +368,7 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 h1:9NWlQfY2ePejTmfwUH1OWwmznFa+0kKcHGPDvcPza9M= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 h1:m8v1xLLLzMe1m5P+gCTF8nJB9epwZQUBERm20Oy1poQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -253,20 +388,30 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.27.4/go.mod h1:O3smaaX15NfxjzILfiln1D8Z3+gEYpjEpiNA/1EVK1Y= k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +k8s.io/apiserver v0.27.2 h1:p+tjwrcQEZDrEorCZV2/qE8osGTINPuS5ZNqWAvKm5E= k8s.io/client-go v0.27.4/go.mod h1:ragcly7lUlN0SRPk5/ZkGnDjPknzb37TICq07WhI6Xc= +k8s.io/code-generator v0.27.2 h1:RmK0CnU5qRaK6WRtSyWNODmfTZNoJbrizpVcsgbtrvI= +k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo= k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kms v0.27.2 h1:wCdmPCa3kubcVd3AssOeaVjLQSu45k5g/vruJ3iqwDU= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From 6eaec67f7fa481553cf11f17b529648c887fcf32 Mon Sep 17 00:00:00 2001 From: zhujingyang <72259332+zjy365@users.noreply.github.com> Date: Sat, 23 Dec 2023 12:23:35 +0800 Subject: [PATCH 15/38] fix:db auth & template develop (#4445) Signed-off-by: jingyang <3161362058@qq.com> --- .../src/components/Table/index.tsx | 99 ++++++++++--------- .../providers/applaunchpad/src/pages/_app.tsx | 56 +++++------ .../src/pages/apps/components/empty.tsx | 8 +- .../src/services/backend/response.ts | 3 +- .../src/pages/jobs/components/empty.tsx | 8 +- .../dbprovider/src/components/Menu/index.tsx | 12 ++- .../src/components/RangeDate/index.tsx | 20 +--- .../dbprovider/src/components/Table/index.tsx | 93 +++++++++-------- .../dbprovider/src/constants/theme.ts | 5 + .../providers/dbprovider/src/pages/_app.tsx | 32 +++--- .../src/pages/db/detail/components/Header.tsx | 6 +- .../dbprovider/src/pages/db/detail/index.tsx | 2 +- .../src/pages/db/edit/components/Form.tsx | 2 +- .../src/pages/dbs/components/dbList.tsx | 9 +- .../src/pages/dbs/components/empty.tsx | 8 +- .../providers/dbprovider/src/store/env.ts | 19 ++-- .../template/src/pages/develop/index.tsx | 35 +++---- .../template/src/services/backend/response.ts | 2 +- 18 files changed, 208 insertions(+), 211 deletions(-) diff --git a/frontend/providers/applaunchpad/src/components/Table/index.tsx b/frontend/providers/applaunchpad/src/components/Table/index.tsx index 2f0f98ea0fe..f0970f15912 100644 --- a/frontend/providers/applaunchpad/src/components/Table/index.tsx +++ b/frontend/providers/applaunchpad/src/components/Table/index.tsx @@ -16,54 +16,65 @@ interface Props extends BoxProps { const Table = ({ columns, data, itemClass = '' }: Props) => { const { t } = useTranslation(); return ( - - {columns.map((item, i) => ( - + + {columns.map((item, i) => ( + + {t(item.title)} + + ))} + + {data.map((item: any, index1) => ( + - {t(item.title)} - + {columns.map((col, index2) => ( + + {col.render ? col.render(item) : col.dataIndex ? `${item[col.dataIndex]}` : ''} + + ))} + ))} - {data.map((item: any, index1) => - columns.map((col, index2) => ( - - {col.render ? col.render(item) : col.dataIndex ? `${item[col.dataIndex]}` : ''} - - )) - )} - + ); }; diff --git a/frontend/providers/applaunchpad/src/pages/_app.tsx b/frontend/providers/applaunchpad/src/pages/_app.tsx index 69535496694..b6512c600ad 100644 --- a/frontend/providers/applaunchpad/src/pages/_app.tsx +++ b/frontend/providers/applaunchpad/src/pages/_app.tsx @@ -2,7 +2,7 @@ import { theme } from '@/constants/theme'; import { useConfirm } from '@/hooks/useConfirm'; import { useLoading } from '@/hooks/useLoading'; import { useGlobalStore } from '@/store/global'; -import { loadInitData } from '@/store/static'; +import { SEALOS_DOMAIN, loadInitData } from '@/store/static'; import { useUserStore } from '@/store/user'; import { getLangStore, setLangStore } from '@/utils/cookieUtils'; import { ChakraProvider } from '@chakra-ui/react'; @@ -50,7 +50,6 @@ const App = ({ Component, pageProps }: AppProps) => { }); useEffect(() => { - NProgress.start(); const response = createSealosApp(); (async () => { const { SEALOS_DOMAIN, FORM_SLIDER_LIST_CONFIG } = await (() => loadInitData())(); @@ -69,14 +68,12 @@ const App = ({ Component, pageProps }: AppProps) => { console.log('App is not running in desktop'); if (!process.env.NEXT_PUBLIC_MOCK_USER) { localStorage.removeItem('session'); - openConfirm(() => { window.open(`https://${SEALOS_DOMAIN}`, '_self'); })(); } } })(); - NProgress.done(); return response; }, []); @@ -133,35 +130,32 @@ const App = ({ Component, pageProps }: AppProps) => { i18n?.changeLanguage?.(lang); }, [refresh, router.pathname]); - // InternalAppCall - const setupInternalAppCallListener = async () => { - try { - const envs = await getPlatformEnv(); - const event = async (e: MessageEvent) => { - const whitelist = [`https://${envs?.domain}`]; - if (!whitelist.includes(e.origin)) { - return; - } - try { - if (e.data?.type === 'InternalAppCall' && e.data?.name) { - router.push({ - pathname: '/app/detail', - query: { - name: e.data.name - } - }); - } - } catch (error) { - console.log(error, 'error'); - } - }; - window.addEventListener('message', event); - return () => window.removeEventListener('message', event); - } catch (error) {} - }; useEffect(() => { + const setupInternalAppCallListener = async () => { + try { + const event = async (e: MessageEvent) => { + const whitelist = [`https://${SEALOS_DOMAIN}`]; + if (!whitelist.includes(e.origin)) { + return; + } + try { + if (e.data?.type === 'InternalAppCall' && e.data?.name) { + router.push({ + pathname: '/app/detail', + query: { + name: e.data.name + } + }); + } + } catch (error) { + console.log(error, 'error'); + } + }; + window.addEventListener('message', event); + return () => window.removeEventListener('message', event); + } catch (error) {} + }; setupInternalAppCallListener(); - // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( diff --git a/frontend/providers/applaunchpad/src/pages/apps/components/empty.tsx b/frontend/providers/applaunchpad/src/pages/apps/components/empty.tsx index 49bd2b84ac3..2acb4c7c00c 100644 --- a/frontend/providers/applaunchpad/src/pages/apps/components/empty.tsx +++ b/frontend/providers/applaunchpad/src/pages/apps/components/empty.tsx @@ -19,13 +19,7 @@ const Empty = () => { > {t("You haven't created any application yet.")} - diff --git a/frontend/providers/applaunchpad/src/services/backend/response.ts b/frontend/providers/applaunchpad/src/services/backend/response.ts index 958ec3bf512..129837b802d 100644 --- a/frontend/providers/applaunchpad/src/services/backend/response.ts +++ b/frontend/providers/applaunchpad/src/services/backend/response.ts @@ -26,8 +26,7 @@ export const jsonRes = ( } else if (error?.code && error.code in ERROR_TEXT) { msg = ERROR_TEXT[error.code]; } - console.log('error:', error); - console.log('error message:', msg); + console.error('===jsonRes error===\n ', error); } res.json({ diff --git a/frontend/providers/cronjob/src/pages/jobs/components/empty.tsx b/frontend/providers/cronjob/src/pages/jobs/components/empty.tsx index 1656bcdc95f..958dcc35486 100644 --- a/frontend/providers/cronjob/src/pages/jobs/components/empty.tsx +++ b/frontend/providers/cronjob/src/pages/jobs/components/empty.tsx @@ -19,13 +19,7 @@ const Empty = () => { > {t('job.You have no tasks yet')} - diff --git a/frontend/providers/dbprovider/src/components/Menu/index.tsx b/frontend/providers/dbprovider/src/components/Menu/index.tsx index 7740239c402..d46c4ce7c22 100644 --- a/frontend/providers/dbprovider/src/components/Menu/index.tsx +++ b/frontend/providers/dbprovider/src/components/Menu/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Menu, MenuList, MenuItem } from '@chakra-ui/react'; +import { Menu, MenuList, MenuItem, MenuItemProps } from '@chakra-ui/react'; interface Props { width: number; @@ -8,11 +8,12 @@ interface Props { isActive?: boolean; child: React.ReactNode; onClick: () => void; + isDisabled?: boolean; }[]; } const MyMenu = ({ width, Button, menuList }: Props) => { - const menuItemStyles = { + const menuItemStyles: MenuItemProps = { borderRadius: 'sm', py: 2, display: 'flex', @@ -20,6 +21,12 @@ const MyMenu = ({ width, Button, menuList }: Props) => { _hover: { backgroundColor: 'myWhite.600', color: 'hover.blue' + }, + _disabled: { + _hover: { + color: '#485264', + cursor: 'not-allowed' + } } }; @@ -34,6 +41,7 @@ const MyMenu = ({ width, Button, menuList }: Props) => { > {menuList.map((item, i) => ( { const { t } = useTranslation(); return ( - - {columns.map((item, i) => ( - + + {columns.map((item, i) => ( + + {t(item.title)} + + ))} + + {data.map((item: any, index1) => ( + - {t(item.title)} - + {columns.map((col, index2) => ( + + {col.render ? col.render(item) : col.dataIndex ? `${item[col.dataIndex]}` : ''} + + ))} + ))} - {data.map((item: any, index1) => - columns.map((col, index2) => ( - - {col.render ? col.render(item) : col.dataIndex ? `${item[col.dataIndex]}` : ''} - - )) - )} - + ); }; diff --git a/frontend/providers/dbprovider/src/constants/theme.ts b/frontend/providers/dbprovider/src/constants/theme.ts index 257ca7a96a6..4464192349e 100644 --- a/frontend/providers/dbprovider/src/constants/theme.ts +++ b/frontend/providers/dbprovider/src/constants/theme.ts @@ -76,6 +76,11 @@ const Button = defineStyleConfig({ borderColor: 'myGray.100', _hover: { color: 'hover.blue' + }, + _disabled: { + _hover: { + color: 'myGray.900' + } } } }, diff --git a/frontend/providers/dbprovider/src/pages/_app.tsx b/frontend/providers/dbprovider/src/pages/_app.tsx index 62ff85e6c2d..d68dee90e2e 100644 --- a/frontend/providers/dbprovider/src/pages/_app.tsx +++ b/frontend/providers/dbprovider/src/pages/_app.tsx @@ -11,7 +11,7 @@ import { appWithTranslation, useTranslation } from 'next-i18next'; import type { AppProps } from 'next/app'; import Head from 'next/head'; import Router, { useRouter } from 'next/router'; -import NProgress from 'nprogress'; //nprogress module +import NProgress from 'nprogress'; import { useEffect, useState } from 'react'; import { EVENT_NAME } from 'sealos-desktop-sdk'; import { createSealosApp, sealosApp } from 'sealos-desktop-sdk/app'; @@ -19,7 +19,6 @@ import useEnvStore from '@/store/env'; import '@/styles/reset.scss'; import 'nprogress/nprogress.css'; -import 'react-day-picker/dist/style.css'; //Binding events. Router.events.on('routeChangeStart', () => NProgress.start()); @@ -50,31 +49,29 @@ function App({ Component, pageProps }: AppProps) { }); useEffect(() => { - initSystemEnv(); - }, [initSystemEnv]); - - useEffect(() => { - NProgress.start(); const response = createSealosApp(); - (async () => { + const { domain } = await initSystemEnv(); try { - const res = await sealosApp.getSession(); - localStorage.setItem('session', JSON.stringify(res)); + const newSession = JSON.stringify(await sealosApp.getSession()); + const oldSession = localStorage.getItem('session'); + if (newSession && newSession !== oldSession) { + localStorage.setItem('session', newSession); + window.location.reload(); + } console.log('app init success'); } catch (err) { console.log('App is not running in desktop'); if (!process.env.NEXT_PUBLIC_MOCK_USER) { localStorage.removeItem('session'); openConfirm(() => { - window.open(`https://${SystemEnv.domain}`, '_self'); + window.open(`https://${domain}`, '_self'); })(); } } })(); - NProgress.done(); return response; - }, [SystemEnv.domain, openConfirm]); + }, []); // add resize event useEffect(() => { @@ -93,6 +90,9 @@ function App({ Component, pageProps }: AppProps) { // init useEffect(() => { + getUserPrice(); + getDBVersion(); + const changeI18n = async (data: any) => { const lastLang = getLangStore(); const newLang = data.currentLanguage; @@ -103,9 +103,6 @@ function App({ Component, pageProps }: AppProps) { } }; - getUserPrice(); - getDBVersion(); - (async () => { try { const lang = await sealosApp.getLanguage(); @@ -138,7 +135,6 @@ function App({ Component, pageProps }: AppProps) { }, [refresh, router.asPath]); useEffect(() => { - // InternalAppCall const setupInternalAppCallListener = async () => { try { const event = async (e: MessageEvent) => { @@ -164,7 +160,7 @@ function App({ Component, pageProps }: AppProps) { } catch (error) {} }; setupInternalAppCallListener(); - }, [SystemEnv, router]); + }, [SystemEnv.domain, router]); return ( <> diff --git a/frontend/providers/dbprovider/src/pages/db/detail/components/Header.tsx b/frontend/providers/dbprovider/src/pages/db/detail/components/Header.tsx index 4244d0d5d9e..76358a61dc4 100644 --- a/frontend/providers/dbprovider/src/pages/db/detail/components/Header.tsx +++ b/frontend/providers/dbprovider/src/pages/db/detail/components/Header.tsx @@ -150,6 +150,7 @@ const Header = ({ isLoading={loading} variant={'base'} bg={'white'} + isDisabled={db.status.value === 'Updating'} onClick={() => { router.push(`/db/edit?name=${db.dbName}`); }} @@ -179,6 +180,7 @@ const Header = ({ isLoading={loading} variant={'base'} bg={'white'} + isDisabled={db.status.value === 'Updating'} onClick={onOpenPause(handlePauseApp)} > {t('Pause')} @@ -210,6 +212,7 @@ const Header = ({ variant={'base'} bg={'white'} leftIcon={} + isDisabled={db.status.value === 'Updating'} onClick={openRestartConfirm(handleRestartApp)} isLoading={loading} > @@ -226,7 +229,8 @@ const Header = ({ _hover={{ color: '#FF324A' }} - isDisabled={loading} + isLoading={loading} + isDisabled={db.status.value === 'Updating'} onClick={onOpenDelModal} > {t('Delete')} diff --git a/frontend/providers/dbprovider/src/pages/db/detail/index.tsx b/frontend/providers/dbprovider/src/pages/db/detail/index.tsx index 54c33d0fe09..0d984c514d9 100644 --- a/frontend/providers/dbprovider/src/pages/db/detail/index.tsx +++ b/frontend/providers/dbprovider/src/pages/db/detail/index.tsx @@ -75,7 +75,7 @@ const AppDetail = ({ const [showSlider, setShowSlider] = useState(false); useQuery([dbName, 'loadDBDetail', 'intervalLoadPods'], () => loadDBDetail(dbName), { - // refetchInterval: 3000, + refetchInterval: 3000, onError(err) { router.replace('/dbs'); toast({ diff --git a/frontend/providers/dbprovider/src/pages/db/edit/components/Form.tsx b/frontend/providers/dbprovider/src/pages/db/edit/components/Form.tsx index 6ed0ae2b2e7..202bd23c08c 100644 --- a/frontend/providers/dbprovider/src/pages/db/edit/components/Form.tsx +++ b/frontend/providers/dbprovider/src/pages/db/edit/components/Form.tsx @@ -348,7 +348,7 @@ const Form = ({ {t('Update')} ), - onClick: () => router.push(`/db/edit?name=${item.name}`) + onClick: () => router.push(`/db/edit?name=${item.name}`), + isDisabled: item.status.value === 'Updating' }, { child: ( @@ -209,7 +210,8 @@ const DBList = ({ {t('Restart')} ), - onClick: () => handleRestartApp(item) + onClick: () => handleRestartApp(item), + isDisabled: item.status.value === 'Updating' } ]), ...(item.status.value === DBStatusEnum.Running @@ -233,7 +235,8 @@ const DBList = ({ {t('Delete')} ), - onClick: () => setDelAppName(item.name) + onClick: () => setDelAppName(item.name), + isDisabled: item.status.value === 'Updating' } ]} /> diff --git a/frontend/providers/dbprovider/src/pages/dbs/components/empty.tsx b/frontend/providers/dbprovider/src/pages/dbs/components/empty.tsx index 8d1d0c0add9..81fdf7aef37 100644 --- a/frontend/providers/dbprovider/src/pages/dbs/components/empty.tsx +++ b/frontend/providers/dbprovider/src/pages/dbs/components/empty.tsx @@ -19,13 +19,7 @@ const Empty = () => { > {t('DataBase Empty')} - diff --git a/frontend/providers/dbprovider/src/store/env.ts b/frontend/providers/dbprovider/src/store/env.ts index eeffd3e03f3..8762ff96b47 100644 --- a/frontend/providers/dbprovider/src/store/env.ts +++ b/frontend/providers/dbprovider/src/store/env.ts @@ -8,7 +8,7 @@ export let Domain: string | undefined; type EnvState = { SystemEnv: SystemEnvResponse; - initSystemEnv: () => void; + initSystemEnv: () => Promise; }; const useEnvStore = create()( @@ -21,16 +21,13 @@ const useEnvStore = create()( BACKUP_ENABLED: false }, initSystemEnv: async () => { - try { - const data = await getAppEnv(); - Domain = data.domain; - StorageClassName = data.env_storage_className; - set((state) => { - state.SystemEnv = data; - }); - } catch (error) { - console.log(error, 'get system env'); - } + const data = await getAppEnv(); + Domain = data.domain; + StorageClassName = data.env_storage_className; + set((state) => { + state.SystemEnv = data; + }); + return data; } })) ); diff --git a/frontend/providers/template/src/pages/develop/index.tsx b/frontend/providers/template/src/pages/develop/index.tsx index eac073b60b0..798d2dfedf9 100644 --- a/frontend/providers/template/src/pages/develop/index.tsx +++ b/frontend/providers/template/src/pages/develop/index.tsx @@ -29,17 +29,8 @@ import BreadCrumbHeader from './components/BreadCrumbHeader'; import Form from './components/Form'; import YamlList from './components/YamlList'; import { type EditorState } from '@codemirror/state'; -import dynamic from 'next/dynamic'; -const Editor = dynamic(() => import('./components/Editor'), { - loading() { - return ( -
- -
- ); - }, - ssr: false -}); +import Editor from './components/Editor'; + export default function Develop() { const { t } = useTranslation(); const { toast } = useToast(); @@ -56,7 +47,7 @@ export default function Develop() { const onYamlChange = debounce((state: EditorState) => { const value = state.doc.toString(); parseTemplate(value); - }, 500); + }, 800); const getYamlSource = (str: string): TemplateSourceType => { const yamlData = JsYaml.loadAll(str); @@ -202,6 +193,7 @@ export default function Develop() { }, [yamlList]); const formalApply = async () => { + setIsLoading(true); try { if (yamlList.length !== 0 && SuccessfulDryRun.current) { const result: string[] = await postDeployApp(yamlList.map((item) => item.value)); @@ -213,6 +205,7 @@ export default function Develop() { } catch (error) { console.log(error, 'FormalApply'); } + setIsLoading(false); }; return ( @@ -248,13 +241,17 @@ export default function Develop() { {t('develop.Please enter YAML code')} - onYamlChange(s)} - /> + {platformEnvs && ( + { + onYamlChange(s); + }} + /> + )} {/* right */} diff --git a/frontend/providers/template/src/services/backend/response.ts b/frontend/providers/template/src/services/backend/response.ts index dd675391fd6..129837b802d 100644 --- a/frontend/providers/template/src/services/backend/response.ts +++ b/frontend/providers/template/src/services/backend/response.ts @@ -26,7 +26,7 @@ export const jsonRes = ( } else if (error?.code && error.code in ERROR_TEXT) { msg = ERROR_TEXT[error.code]; } - console.error('jsonRes error------------\n ', error); + console.error('===jsonRes error===\n ', error); } res.json({ From d73becbf408d9165934f6c41a14105a03c92265c Mon Sep 17 00:00:00 2001 From: zhujingyang <72259332+zjy365@users.noreply.github.com> Date: Mon, 25 Dec 2023 16:17:13 +0800 Subject: [PATCH 16/38] fix:privoder logo svg (#4446) Signed-off-by: jingyang <3161362058@qq.com> --- frontend/providers/dbprovider/public/logo.svg | 6 +++++- frontend/providers/terminal/public/logo.svg | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/providers/dbprovider/public/logo.svg b/frontend/providers/dbprovider/public/logo.svg index 68fee8b7681..d09f08ca92c 100644 --- a/frontend/providers/dbprovider/public/logo.svg +++ b/frontend/providers/dbprovider/public/logo.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/frontend/providers/terminal/public/logo.svg b/frontend/providers/terminal/public/logo.svg index a2207d14c7f..1a482cb713a 100644 --- a/frontend/providers/terminal/public/logo.svg +++ b/frontend/providers/terminal/public/logo.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + \ No newline at end of file From a35524dfd3c7cacbc43ee92ac68cc7b35f235587 Mon Sep 17 00:00:00 2001 From: xuziyi Date: Tue, 2 Jan 2024 14:53:11 +0800 Subject: [PATCH 17/38] Separate database svc and minio svc (#4447) * separate database svc and minio svc * delete OBJECT_STORAGE_INSTANCE env * fix deploy.yaml --- service/database/config/config.yml | 2 - service/database/deploy/manifests/deploy.yaml | 8 +- service/database/main.go | 47 +--- service/database/server/server.go | 194 ++--------------- service/minio/Dockerfile | 9 + service/minio/Makefile | 55 +++++ service/minio/deploy/Kubefile | 5 + service/minio/deploy/manifests/deploy.yaml | 88 ++++++++ service/minio/main.go | 35 +++ service/minio/server/server.go | 38 ++++ service/{database => pkg}/api/req.go | 0 service/{database => pkg}/request/req.go | 2 +- service/{database => pkg}/server/config.go | 0 service/pkg/server/server.go | 202 ++++++++++++++++++ 14 files changed, 461 insertions(+), 224 deletions(-) delete mode 100644 service/database/config/config.yml create mode 100644 service/minio/Dockerfile create mode 100644 service/minio/Makefile create mode 100644 service/minio/deploy/Kubefile create mode 100644 service/minio/deploy/manifests/deploy.yaml create mode 100644 service/minio/main.go create mode 100644 service/minio/server/server.go rename service/{database => pkg}/api/req.go (100%) rename service/{database => pkg}/request/req.go (98%) rename service/{database => pkg}/server/config.go (100%) create mode 100644 service/pkg/server/server.go diff --git a/service/database/config/config.yml b/service/database/config/config.yml deleted file mode 100644 index 4683ee496c5..00000000000 --- a/service/database/config/config.yml +++ /dev/null @@ -1,2 +0,0 @@ -server: - addr: ":9090" \ No newline at end of file diff --git a/service/database/deploy/manifests/deploy.yaml b/service/database/deploy/manifests/deploy.yaml index 4e9b0032668..22c56966c07 100644 --- a/service/database/deploy/manifests/deploy.yaml +++ b/service/database/deploy/manifests/deploy.yaml @@ -37,7 +37,6 @@ spec: env: - name: PROMETHEUS_SERVICE_HOST value: http://kb-addon-prometheus-server.kb-system.svc.cluster.local - - name: OBJECT_STORAGE_INSTANCE image: ghcr.io/labring/sealos-database-service:latest imagePullPolicy: Always name: database-monitor @@ -45,9 +44,12 @@ spec: - containerPort: 9090 protocol: TCP resources: + limits: + cpu: 500m + memory: 1024Mi requests: - cpu: 1m - memory: 500M + cpu: 5m + memory: 64Mi securityContext: allowPrivilegeEscalation: false capabilities: diff --git a/service/database/main.go b/service/database/main.go index 73cc8b5ba26..e6183a1d740 100644 --- a/service/database/main.go +++ b/service/database/main.go @@ -4,53 +4,20 @@ import ( "flag" "fmt" "log" - "net" - "net/http" "os" - "github.com/labring/sealos/service/database/server" + dbserver "github.com/labring/sealos/service/database/server" + "github.com/labring/sealos/service/pkg/server" ) -type RestartableServer struct { - configFile string - // server *server.PromServer - // hs *http.Server -} - -func (rs *RestartableServer) Serve(c *server.Config) { - var ps, err = server.NewPromServer(c) - if err != nil { - fmt.Printf("Failed to create auth server: %s\n", err) - return - } - - hs := &http.Server{ - Addr: c.Server.ListenAddress, - Handler: ps, - } - - var listener net.Listener - listener, err = net.Listen("tcp", c.Server.ListenAddress) - if err != nil { - fmt.Println(err) - return - } - fmt.Printf("Serve on %s\n", c.Server.ListenAddress) - - if err := hs.Serve(listener); err != nil { - fmt.Println(err) - return - } -} - func main() { - log.SetOutput(os.Stdout) // 将日志输出定向到标准输出(stdout) + log.SetOutput(os.Stdout) log.SetFlags(log.LstdFlags | log.Lshortfile) flag.Parse() cf := flag.Arg(0) if cf == "" { - fmt.Println("Config file not sepcified") + fmt.Println("The config file is not specified") return } @@ -59,8 +26,10 @@ func main() { fmt.Println(err) return } - rs := RestartableServer{ - configFile: cf, + + rs := dbserver.DatabaseServer{ + ConfigFile: cf, } + rs.Serve(config) } diff --git a/service/database/server/server.go b/service/database/server/server.go index f3d7cdc6253..bba3155633a 100644 --- a/service/database/server/server.go +++ b/service/database/server/server.go @@ -1,202 +1,38 @@ package server import ( - "encoding/json" "fmt" - "log" + "net" "net/http" - "net/url" - "text/template" - "github.com/labring/sealos/service/pkg/auth" - - "github.com/labring/sealos/service/database/api" - "github.com/labring/sealos/service/database/request" + "github.com/labring/sealos/service/pkg/server" ) -type PromServer struct { - Config *Config -} - -func NewPromServer(c *Config) (*PromServer, error) { - ps := &PromServer{ - Config: c, - } - return ps, nil -} - -func (ps *PromServer) Authenticate(pr *api.PromRequest) error { - return auth.Authenticate(pr.NS, pr.Pwd) -} - -func (ps *PromServer) Request(pr *api.PromRequest) (*api.QueryResult, error) { - body, err := request.PrometheusPre(pr) - if err != nil { - return nil, err - } - var result *api.QueryResult - if err := json.Unmarshal(body, &result); err != nil { - return nil, err - } - return result, err -} - -func (ps *PromServer) DBReq(pr *api.PromRequest) (*api.QueryResult, error) { - body, err := request.PrometheusNew(pr) - if err != nil { - return nil, err - } - var result *api.QueryResult - if err := json.Unmarshal(body, &result); err != nil { - return nil, err - } - return result, nil -} - -func (ps *PromServer) ParseRequest(req *http.Request) (*api.PromRequest, error) { - pr := &api.PromRequest{} - - auth := req.Header.Get("Authorization") - - if pwd, err := url.PathUnescape(auth); err == nil { - pr.Pwd = pwd - } else { - return nil, err - } - if pr.Pwd == "" { - return nil, api.ErrEmptyKubeconfig - } - - if err := req.ParseForm(); err != nil { - return nil, err - } - - for key, val := range req.Form { - switch key { - case "query": - pr.Query = val[0] - case "step": - pr.Range.Step = val[0] - case "start": - pr.Range.Start = val[0] - case "end": - pr.Range.End = val[0] - case "time": - pr.Range.Time = val[0] - case "namespace": - pr.NS = val[0] - case "type": - pr.Type = val[0] - case "app": - pr.Cluster = val[0] - } - } - - if pr.NS == "" || pr.Query == "" { - return nil, api.ErrUncompleteParam - } - - return pr, nil -} - -// 获取客户端请求的信息 -func (ps *PromServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - pathPrefix := "" - switch { - case req.URL.Path == pathPrefix+"/query": // 将废弃 - ps.doReqPre(rw, req) - case req.URL.Path == pathPrefix+"/q": - ps.doReqNew(rw, req) - default: - http.Error(rw, "Not found", http.StatusNotFound) - return - } -} - -func (ps *PromServer) doReqNew(rw http.ResponseWriter, req *http.Request) { - pr, err := ps.ParseRequest(req) - if err != nil { - http.Error(rw, fmt.Sprintf("Bad request (%s)", err), http.StatusBadRequest) - log.Printf("Bad request (%s)\n", err) - return - } - - if err := ps.Authenticate(pr); err != nil { - http.Error(rw, fmt.Sprintf("Authentication failed (%s)", err), http.StatusInternalServerError) - log.Printf("Authentication failed (%s)\n", err) - return - } - - res, err := ps.DBReq(pr) - if err != nil { - http.Error(rw, fmt.Sprintf("Query failed (%s)", err), http.StatusInternalServerError) - log.Printf("Query failed (%s)\n", err) - return - } - - result, err := json.Marshal(res) - if err != nil { - http.Error(rw, "Result failed (invalid query expression)", http.StatusInternalServerError) - log.Printf("Reulst failed (%s)\n", err) - return - } - - rw.Header().Set("Content-Type", "application/json") - - tmpl := template.New("responseTemplate").Delims("{{", "}}") - tmpl, err = tmpl.Parse(`{{.}}`) - if err != nil { - log.Printf("template failed: %s\n", err) - http.Error(rw, "Internal Server Error", http.StatusInternalServerError) - return - } - if err = tmpl.Execute(rw, string(result)); err != nil { - log.Printf("Reulst failed: %s\n", err) - http.Error(rw, "Internal Server Error", http.StatusInternalServerError) - return - } +type DatabaseServer struct { + ConfigFile string } -func (ps *PromServer) doReqPre(rw http.ResponseWriter, req *http.Request) { - pr, err := ps.ParseRequest(req) +func (rs *DatabaseServer) Serve(c *server.Config) { + ps, err := server.NewPromServer(c) if err != nil { - http.Error(rw, fmt.Sprintf("Bad request (%s)", err), http.StatusBadRequest) - log.Printf("Bad request (%s)\n", err) + fmt.Printf("Failed to create auth server: %s\n", err) return } - if err := ps.Authenticate(pr); err != nil { - http.Error(rw, fmt.Sprintf("Authentication failed (%s)", err), http.StatusInternalServerError) - log.Printf("Authentication failed (%s)\n", err) - log.Printf("Kubeconfig (%s)\n", pr.Pwd) + hs := &http.Server{ + Addr: c.Server.ListenAddress, + Handler: ps, } - res, err := ps.Request(pr) + listener, err := net.Listen("tcp", c.Server.ListenAddress) if err != nil { - http.Error(rw, fmt.Sprintf("Query failed (%s)", err), http.StatusInternalServerError) - log.Printf("Query failed (%s)\n", err) + fmt.Println(err) return } + fmt.Printf("Serve on %s\n", c.Server.ListenAddress) - result, err := json.Marshal(res) - if err != nil { - http.Error(rw, "Result failed (invalid query expression)", http.StatusInternalServerError) - log.Printf("Reulst failed (%s)\n", err) - return - } - - rw.Header().Set("Content-Type", "application/json") - - tmpl := template.New("responseTemplate").Delims("{{", "}}") - tmpl, err = tmpl.Parse(`{{.}}`) - if err != nil { - log.Printf("template failed: %s\n", err) - http.Error(rw, "Internal Server Error", http.StatusInternalServerError) - return - } - if err = tmpl.Execute(rw, string(result)); err != nil { - log.Printf("Reulst failed: %s\n", err) - http.Error(rw, "Internal Server Error", http.StatusInternalServerError) + if err := hs.Serve(listener); err != nil { + fmt.Println(err) return } } diff --git a/service/minio/Dockerfile b/service/minio/Dockerfile new file mode 100644 index 00000000000..565b0de418b --- /dev/null +++ b/service/minio/Dockerfile @@ -0,0 +1,9 @@ +# FROM scratch +FROM gcr.io/distroless/static:nonroot +# FROM gengweifeng/gcr-io-distroless-static-nonroot +ARG TARGETARCH +COPY bin/service-minio-$TARGETARCH /manager +EXPOSE 9090 +USER 65532:65532 + +ENTRYPOINT ["/manager"] \ No newline at end of file diff --git a/service/minio/Makefile b/service/minio/Makefile new file mode 100644 index 00000000000..0fb3c95d844 --- /dev/null +++ b/service/minio/Makefile @@ -0,0 +1,55 @@ +IMG ?= ghcr.io/labring/sealos-minio-service:latest + +# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +ifeq (,$(shell go env GOBIN)) +GOBIN=$(shell go env GOPATH)/bin +else +GOBIN=$(shell go env GOBIN) +endif + +# only support linux, non cgo +PLATFORMS ?= linux_arm64 linux_amd64 +GOOS=linux +CGO_ENABLED=0 +GOARCH=$(shell go env GOARCH) + +GO_BUILD_FLAGS=-trimpath -ldflags "-s -w" + +.PHONY: all +all: build + +##@ General + +# The help target prints out all targets with their descriptions organized +# beneath their categories. The categories are represented by '##@' and the +# target descriptions by '##'. The awk commands is responsible for reading the +# entire set of makefiles included in this invocation, looking for lines of the +# file as xyz: ## something, and then pretty-format the target and help. Then, +# if there's a line with ##@ something, that gets pretty-printed as a category. +# More info on the usage of ANSI control characters for terminal formatting: +# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters +# More info on the awk command: +# http://linuxcommand.org/lc3_adv_awk.php + +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +##@ Build + +.PHONY: clean +clean: + rm -f $(SERVICE_NAME) + +.PHONY: build +build: clean ## Build service-hub binary. + CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) go build $(GO_BUILD_FLAGS) -o bin/manager main.go + +.PHONY: docker-build +docker-build: build + mv bin/manager bin/service-minio-${TARGETARCH} + docker build -t $(IMG) . + +.PHONY: docker-push +docker-push: + docker push $(IMG) diff --git a/service/minio/deploy/Kubefile b/service/minio/deploy/Kubefile new file mode 100644 index 00000000000..035ec02f5a0 --- /dev/null +++ b/service/minio/deploy/Kubefile @@ -0,0 +1,5 @@ +FROM scratch +COPY registry registry +COPY manifests manifests + +CMD ["kubectl apply -f manifests/deploy.yaml"] \ No newline at end of file diff --git a/service/minio/deploy/manifests/deploy.yaml b/service/minio/deploy/manifests/deploy.yaml new file mode 100644 index 00000000000..ee6c656c288 --- /dev/null +++ b/service/minio/deploy/manifests/deploy.yaml @@ -0,0 +1,88 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app: object-storage-monitor + name: object-storage-monitor-config + namespace: objectstorage-system +data: + config.yml: | + server: + addr: ":9090" +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: object-storage-monitor + name: object-storage-monitor + namespace: sealos +spec: + replicas: 1 + selector: + matchLabels: + app: object-storage-monitor + strategy: + type: Recreate + template: + metadata: + labels: + app: object-storage-monitor + spec: + containers: + - args: + - /config/config.yml + command: + - /manager + env: + - name: PROMETHEUS_SERVICE_HOST + value: http://prometheus-object-storage.objectstorage-system.svc.cluster.local:9090 + - name: OBJECT_STORAGE_INSTANCE + value: object-storage.objectstorage-system.svc.cluster.local:80 + image: ghcr.io/labring/sealos-minio-service:latest + imagePullPolicy: Always + name: object-storage-monitor + ports: + - containerPort: 9090 + protocol: TCP + resources: + limits: + cpu: 500m + memory: 1024Mi + requests: + cpu: 5m + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsNonRoot: true + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /config + name: config-vol + dnsPolicy: ClusterFirst + restartPolicy: Always + volumes: + - configMap: + defaultMode: 420 + name: object-storage-monitor-config + name: config-vol +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: object-storage-monitor + name: object-storage-monitor + namespace: objectstorage-system +spec: + ports: + - name: http + port: 9090 + protocol: TCP + targetPort: 9090 + selector: + app: object-storage-monitor diff --git a/service/minio/main.go b/service/minio/main.go new file mode 100644 index 00000000000..b0edc2ef985 --- /dev/null +++ b/service/minio/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + + minioserver "github.com/labring/sealos/service/minio/server" + "github.com/labring/sealos/service/pkg/server" +) + +func main() { + log.SetOutput(os.Stdout) + log.SetFlags(log.LstdFlags | log.Lshortfile) + flag.Parse() + + cf := flag.Arg(0) + if cf == "" { + fmt.Println("The config file is not specified") + return + } + + config, err := server.InitConfig(cf) + if err != nil { + fmt.Println(err) + return + } + + rs := minioserver.MinioServer{ + ConfigFile: cf, + } + + rs.Serve(config) +} diff --git a/service/minio/server/server.go b/service/minio/server/server.go new file mode 100644 index 00000000000..4f5b9b41091 --- /dev/null +++ b/service/minio/server/server.go @@ -0,0 +1,38 @@ +package server + +import ( + "fmt" + "net" + "net/http" + + "github.com/labring/sealos/service/pkg/server" +) + +type MinioServer struct { + ConfigFile string +} + +func (rs *MinioServer) Serve(c *server.Config) { + ps, err := server.NewPromServer(c) + if err != nil { + fmt.Printf("Failed to create auth server: %s\n", err) + return + } + + hs := &http.Server{ + Addr: c.Server.ListenAddress, + Handler: ps, + } + + listener, err := net.Listen("tcp", c.Server.ListenAddress) + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("Serve on %s\n", c.Server.ListenAddress) + + if err := hs.Serve(listener); err != nil { + fmt.Println(err) + return + } +} diff --git a/service/database/api/req.go b/service/pkg/api/req.go similarity index 100% rename from service/database/api/req.go rename to service/pkg/api/req.go diff --git a/service/database/request/req.go b/service/pkg/request/req.go similarity index 98% rename from service/database/request/req.go rename to service/pkg/request/req.go index 43ca12bc478..e00f072d1fa 100644 --- a/service/database/request/req.go +++ b/service/pkg/request/req.go @@ -10,7 +10,7 @@ import ( "os" "strings" - "github.com/labring/sealos/service/database/api" + "github.com/labring/sealos/service/pkg/api" ) func Request(addr string, params *bytes.Buffer) ([]byte, error) { diff --git a/service/database/server/config.go b/service/pkg/server/config.go similarity index 100% rename from service/database/server/config.go rename to service/pkg/server/config.go diff --git a/service/pkg/server/server.go b/service/pkg/server/server.go new file mode 100644 index 00000000000..53ea30bf08e --- /dev/null +++ b/service/pkg/server/server.go @@ -0,0 +1,202 @@ +package server + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "net/url" + "text/template" + + "github.com/labring/sealos/service/pkg/auth" + + "github.com/labring/sealos/service/pkg/api" + "github.com/labring/sealos/service/pkg/request" +) + +type PromServer struct { + Config *Config +} + +func NewPromServer(c *Config) (*PromServer, error) { + ps := &PromServer{ + Config: c, + } + return ps, nil +} + +func (ps *PromServer) Authenticate(pr *api.PromRequest) error { + return auth.Authenticate(pr.NS, pr.Pwd) +} + +func (ps *PromServer) Request(pr *api.PromRequest) (*api.QueryResult, error) { + body, err := request.PrometheusPre(pr) + if err != nil { + return nil, err + } + var result *api.QueryResult + if err := json.Unmarshal(body, &result); err != nil { + return nil, err + } + return result, err +} + +func (ps *PromServer) DBReq(pr *api.PromRequest) (*api.QueryResult, error) { + body, err := request.PrometheusNew(pr) + if err != nil { + return nil, err + } + var result *api.QueryResult + if err := json.Unmarshal(body, &result); err != nil { + return nil, err + } + return result, nil +} + +func (ps *PromServer) ParseRequest(req *http.Request) (*api.PromRequest, error) { + pr := &api.PromRequest{} + + auth := req.Header.Get("Authorization") + + if pwd, err := url.PathUnescape(auth); err == nil { + pr.Pwd = pwd + } else { + return nil, err + } + if pr.Pwd == "" { + return nil, api.ErrEmptyKubeconfig + } + + if err := req.ParseForm(); err != nil { + return nil, err + } + + for key, val := range req.Form { + switch key { + case "query": + pr.Query = val[0] + case "step": + pr.Range.Step = val[0] + case "start": + pr.Range.Start = val[0] + case "end": + pr.Range.End = val[0] + case "time": + pr.Range.Time = val[0] + case "namespace": + pr.NS = val[0] + case "type": + pr.Type = val[0] + case "app": + pr.Cluster = val[0] + } + } + + if pr.NS == "" || pr.Query == "" { + return nil, api.ErrUncompleteParam + } + + return pr, nil +} + +// 获取客户端请求的信息 +func (ps *PromServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + pathPrefix := "" + switch { + case req.URL.Path == pathPrefix+"/query": // 将废弃 + ps.doReqPre(rw, req) + case req.URL.Path == pathPrefix+"/q": + ps.doReqNew(rw, req) + default: + http.Error(rw, "Not found", http.StatusNotFound) + return + } +} + +func (ps *PromServer) doReqNew(rw http.ResponseWriter, req *http.Request) { + pr, err := ps.ParseRequest(req) + if err != nil { + http.Error(rw, fmt.Sprintf("Bad request (%s)", err), http.StatusBadRequest) + log.Printf("Bad request (%s)\n", err) + return + } + + if err := ps.Authenticate(pr); err != nil { + http.Error(rw, fmt.Sprintf("Authentication failed (%s)", err), http.StatusInternalServerError) + log.Printf("Authentication failed (%s)\n", err) + return + } + + res, err := ps.DBReq(pr) + if err != nil { + http.Error(rw, fmt.Sprintf("Query failed (%s)", err), http.StatusInternalServerError) + log.Printf("Query failed (%s)\n", err) + return + } + + result, err := json.Marshal(res) + if err != nil { + http.Error(rw, "Result failed (invalid query expression)", http.StatusInternalServerError) + log.Printf("Reulst failed (%s)\n", err) + return + } + + rw.Header().Set("Content-Type", "application/json") + + tmpl := template.New("responseTemplate").Delims("{{", "}}") + tmpl, err = tmpl.Parse(`{{.}}`) + if err != nil { + log.Printf("template failed: %s\n", err) + http.Error(rw, "Internal Server Error", http.StatusInternalServerError) + return + } + if err = tmpl.Execute(rw, string(result)); err != nil { + log.Printf("Reulst failed: %s\n", err) + http.Error(rw, "Internal Server Error", http.StatusInternalServerError) + return + } +} + +func (ps *PromServer) doReqPre(rw http.ResponseWriter, req *http.Request) { + pr, err := ps.ParseRequest(req) + if err != nil { + http.Error(rw, fmt.Sprintf("Bad request (%s)", err), http.StatusBadRequest) + log.Printf("Bad request (%s)\n", err) + return + } + + if err := ps.Authenticate(pr); err != nil { + http.Error(rw, fmt.Sprintf("Authentication failed (%s)", err), http.StatusInternalServerError) + log.Printf("Authentication failed (%s)\n", err) + log.Printf("Kubeconfig (%s)\n", pr.Pwd) + } + + res, err := ps.Request(pr) + if err != nil { + http.Error(rw, fmt.Sprintf("Query failed (%s)", err), http.StatusInternalServerError) + log.Printf("Query failed (%s)\n", err) + return + } + + result, err := json.Marshal(res) + if err != nil { + http.Error(rw, "Result failed (invalid query expression)", http.StatusInternalServerError) + log.Printf("Reulst failed (%s)\n", err) + return + } + + rw.Header().Set("Content-Type", "application/json") + + tmpl := template.New("responseTemplate").Delims("{{", "}}") + tmpl, err = tmpl.Parse(`{{.}}`) + if err != nil { + log.Printf("template failed: %s\n", err) + http.Error(rw, "Internal Server Error", http.StatusInternalServerError) + return + } + if err = tmpl.Execute(rw, string(result)); err != nil { + log.Printf("Reulst failed: %s\n", err) + http.Error(rw, "Internal Server Error", http.StatusInternalServerError) + return + } +} From 15279bcdae9412c8f57a155d5d65ae3bb3444e62 Mon Sep 17 00:00:00 2001 From: xuziyi Date: Tue, 2 Jan 2024 15:38:13 +0800 Subject: [PATCH 18/38] add minio service module to workflows (#4450) --- .github/workflows/services.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/services.yml b/.github/workflows/services.yml index 0f0d94333b9..60bdd652afa 100644 --- a/.github/workflows/services.yml +++ b/.github/workflows/services.yml @@ -86,7 +86,7 @@ jobs: strategy: matrix: ## TODO: add more modules - module: [ database, pay, account ] + module: [database, pay, account, minio] steps: - name: Checkout uses: actions/checkout@v3 @@ -181,7 +181,7 @@ jobs: strategy: matrix: ## TODO: add more modules - module: [ database, pay, account ] + module: [database, pay, account, minio] steps: - name: Checkout uses: actions/checkout@v3 From 1ea75428a7046544c4852096ff26d6ddd500a20f Mon Sep 17 00:00:00 2001 From: yy <56745951+lingdie@users.noreply.github.com> Date: Tue, 2 Jan 2024 15:57:23 +0800 Subject: [PATCH 19/38] chore: fix docs link. (#4451) Signed-off-by: yy --- docs/blog/zh-Hans/2023/k8s-multi-tenancy.md | 4 ++-- docs/blog/zh-Hans/2023/what-is-sealos.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/blog/zh-Hans/2023/k8s-multi-tenancy.md b/docs/blog/zh-Hans/2023/k8s-multi-tenancy.md index 42d28054fc1..1cc204dfd7f 100644 --- a/docs/blog/zh-Hans/2023/k8s-multi-tenancy.md +++ b/docs/blog/zh-Hans/2023/k8s-multi-tenancy.md @@ -65,9 +65,9 @@ K8s 本身不具备原生的用户管理系统。因此,需要通过扩展功 Sealos 的设计允许管理员将用户加入特定的命名空间,并对其角色进行管理,从而有效地控制权限。这样管理员就可以细粒度地管理用户权限,确保每个用户只能访问和修改他们被授权的资源。 -![](https://jsd.cdn.zzko.cn/gh/yangchuansheng/imghosting6@main/uPic/2023-11-29-10-34-wknQxI.png) +![](https://cdn.jsdelivr.us/gh/yangchuansheng/imghosting6@main/uPic/2023-11-29-10-34-wknQxI.png) -![](https://jsd.cdn.zzko.cn/gh/yangchuansheng/imghosting6@main/uPic/2023-11-29-10-34-RQFrTB.png) +![](https://cdn.jsdelivr.us/gh/yangchuansheng/imghosting6@main/uPic/2023-11-29-10-34-RQFrTB.png) ### 挑战 3:计量与配额管理 diff --git a/docs/blog/zh-Hans/2023/what-is-sealos.md b/docs/blog/zh-Hans/2023/what-is-sealos.md index 09a81bd3cc7..87d0b653f60 100644 --- a/docs/blog/zh-Hans/2023/what-is-sealos.md +++ b/docs/blog/zh-Hans/2023/what-is-sealos.md @@ -87,7 +87,7 @@ Sealos 并不自己去设定标准,而是严格遵循成熟的体系和事实 从这个新的视角出发,我们发现,实际上并不需要 IaaS。同时,从技术角度来看,PaaS 和 SaaS 本质上是相同的,它们都是应用层面的服务,因此也无需进行过度区分。在新的云内核架构中,我们只需要有效地实现多租户之间的隔离。这并不需要复杂重量级的解决方案。例如,Sealos 提供了一种在不可信公网环境中实现多租户共享一个 K8s 集群的方式。我们利用强隔离容器 (如 Firecracker)、网络策略 (如 Cilium) 以及存储块设备隔离 (如 OpenEBS) 来实现这一目标,不仅成本更低,效果也更好。 -![](https://jsd.cdn.zzko.cn/gh/yangchuansheng/imghosting-test@main/uPic/2023-11-17-15-02-6N4ygp.png) +![](https://cdn.jsdelivr.us/gh/yangchuansheng/imghosting-test@main/uPic/2023-11-17-15-02-6N4ygp.png) #### 提高应用密度和调度效率 From 873894f6d2e5f3962295da2f0eb3d1cbaa36dc33 Mon Sep 17 00:00:00 2001 From: xudaotutou <13435638964@163.com> Date: Tue, 2 Jan 2024 17:36:19 +0800 Subject: [PATCH 20/38] fix(desktop):fix verification code restriction (#4449) --- frontend/desktop/src/pages/api/auth/phone/sms.ts | 10 +++++++--- .../desktop/src/services/backend/db/verifyCode.ts | 15 +++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/frontend/desktop/src/pages/api/auth/phone/sms.ts b/frontend/desktop/src/pages/api/auth/phone/sms.ts index 44033caaeb9..53ec223a7dd 100644 --- a/frontend/desktop/src/pages/api/auth/phone/sms.ts +++ b/frontend/desktop/src/pages/api/auth/phone/sms.ts @@ -20,14 +20,18 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) if (!enableSms()) { throw new Error('SMS is not enabled'); } - const { phoneNumbers } = req.body; - if (!(await checkSendable(phoneNumbers))) { + const { phoneNumbers } = req.body as { phoneNumbers?: string }; + if (!phoneNumbers) + return jsonRes(res, { + message: 'phoneNumbers is invalid', + code: 400 + }); + if (!(await checkSendable({ phone: phoneNumbers }))) { return jsonRes(res, { message: 'code already sent', code: 400 }); } - // randomly generate six bit check code const code = Math.floor(Math.random() * 900000 + 100000).toString(); const sendSmsRequest = new dysmsapi.SendSmsRequest({ diff --git a/frontend/desktop/src/services/backend/db/verifyCode.ts b/frontend/desktop/src/services/backend/db/verifyCode.ts index 3b91f74fcb8..6dad9c4b3ae 100644 --- a/frontend/desktop/src/services/backend/db/verifyCode.ts +++ b/frontend/desktop/src/services/backend/db/verifyCode.ts @@ -3,13 +3,13 @@ import { connectToDatabase } from './mongodb'; type TVerification_Codes = { phone: string; code: string; - createdTime: number; + createdAt: Date; }; async function connectToUserCollection() { const client = await connectToDatabase(); const collection = client.db().collection('verification_codes'); - await collection.createIndex({ createdTime: 1 }, { expireAfterSeconds: 60 * 5 }); + await collection.createIndex({ createdAt: 1 }, { expireAfterSeconds: 60 * 5 }); return collection; } @@ -23,7 +23,7 @@ export async function addOrUpdateCode({ phone, code }: { phone: string; code: st { $set: { code, - createdTime: new Date().getTime() + createdAt: new Date() } }, { @@ -37,10 +37,9 @@ export async function checkSendable({ phone }: { phone: string }) { const codes = await connectToUserCollection(); const result = await codes.findOne({ phone, - createdTime: { + createdAt: { // 在区间范围内找到就是已经发送过了,不能再发了 - $gt: new Date().getTime() - 60 * 1000, - $lt: new Date().getTime() + $gt: new Date(new Date().getTime() - 60 * 1000) } }); return !result; @@ -51,9 +50,9 @@ export async function checkCode({ phone, code }: { phone: string; code: string } const result = await codes.findOne({ phone, code, - createdTime: { + createdAt: { // 5分钟内有效 - $gt: new Date().getTime() - 5 * 60 * 1000 + $gt: new Date(new Date().getTime() - 5 * 60 * 1000) } }); return !!result; From b4daa2df1181598e396f0804b0d0a12fd16079f4 Mon Sep 17 00:00:00 2001 From: Carson Yang Date: Tue, 2 Jan 2024 18:13:20 +0800 Subject: [PATCH 21/38] docs: add master services agreement (#4452) Signed-off-by: Carson Yang --- docs/4.0/docs/msa/privacy-policy.md | 59 ++++++++++++++++ docs/4.0/docs/msa/terms-of-service.md | 68 +++++++++++++++++++ docs/4.0/i18n/zh-Hans/current.json | 4 ++ docs/4.0/i18n/zh-Hans/msa/privacy-policy.md | 62 +++++++++++++++++ docs/4.0/i18n/zh-Hans/msa/terms-of-service.md | 68 +++++++++++++++++++ docs/4.0/sidebar.json | 13 ++++ 6 files changed, 274 insertions(+) create mode 100644 docs/4.0/docs/msa/privacy-policy.md create mode 100644 docs/4.0/docs/msa/terms-of-service.md create mode 100644 docs/4.0/i18n/zh-Hans/msa/privacy-policy.md create mode 100644 docs/4.0/i18n/zh-Hans/msa/terms-of-service.md diff --git a/docs/4.0/docs/msa/privacy-policy.md b/docs/4.0/docs/msa/privacy-policy.md new file mode 100644 index 00000000000..fdf4525f71c --- /dev/null +++ b/docs/4.0/docs/msa/privacy-policy.md @@ -0,0 +1,59 @@ +--- +sidebar_position: 2 +--- + +# Sealos Cloud Privacy Policy + +We prioritize your privacy immensely. This policy details the collection, use, disclosure, and protection of your personal information when you utilize our services. Please thoroughly understand its contents. + +**Information Collection** + +1. We may gather your personal details like name, phone number, email, and address during registration or service usage. +2. We also collect data produced during service use, such as operational logs, IP addresses, and device types. +3. For enhanced user experience, technologies like cookies may be employed to store information related to your service interaction. + +**Information Usage** + +1. The handling of your personal data adheres to legal regulations and user agreements. +2. We utilize the information for improving service quality, innovating new products, and other similar purposes. +3. Collected data might be used for delivering service-related notifications and advertisements. + +**Disclosure of Information** + +1. Your personal data will not be shared with third parties, except under these circumstances: + + 1. With your prior agreement; + 2. When legally or regulatorily required; + 3. To uphold our or other users' legal rights. + +2. We may share your information with affiliated entities or partners, ensuring data security through strict confidentiality. + +**Protection of Information** + +1. We apply various security measures, like encryption and access control, to prevent unauthorized data access, use, or disclosure. +2. Regular safety assessments are conducted on stored personal data to guarantee its security. +3. Should a data leak or similar security incident occur, we'll immediately implement emergency measures and inform you as required by law. + +**User Rights** + +1. You have complete authority to access, correct, or delete your personal data at any time. +2. Opting out of data collection can limit your access to certain service features. +3. You may request a halt in processing your personal data, which might affect service continuation. + +**Privacy Policy Updates** + +1. We may periodically update this policy, and any changes will be published on our service page. Continuing service use implies acceptance of any updated terms. +2. Regularly reviewing this policy is encouraged to stay informed about your data protection. + +**Minor Protection** + +Minors' data protection is crucial to us. If you're a minor, please engage with our services under guardian supervision, ensuring proper data management. + +**Cross-border Data Transfer** + +Considering our servers' diverse locations, your data may be transferred and processed internationally. We assure that cross-border data remains securely protected. + +**Contact Us** + +1. For any questions, suggestions, or complaints about this policy, please reach us via email fanux@sealos.io +2. We are committed to quickly resolving any issues you raise. \ No newline at end of file diff --git a/docs/4.0/docs/msa/terms-of-service.md b/docs/4.0/docs/msa/terms-of-service.md new file mode 100644 index 00000000000..718b60d41c6 --- /dev/null +++ b/docs/4.0/docs/msa/terms-of-service.md @@ -0,0 +1,68 @@ +--- +sidebar_position: 1 +--- + +# Sealos Cloud Terms of Service + +These Sealos Cloud Terms of Service (this “Agreement”) are entered into by and between you and Zhuhai Huanjie Cloud Computing Co., Ltd. (referred to as “we/us” or "the Company") regarding the use of our cloud services (hereafter referred to as "the Service"). We urge you to read and understand every clause, particularly those concerning limitations of our liability, restrictions on your rights, and the terms about dispute resolution and legal jurisdiction. If any aspect of this agreement is not acceptable to you, refrain from registering for or using the Service. + +**Article 1: Scope of Services** + +1. We offer a range of internet-based IT services, including but not limited to storage, computation, and network transmission. +2. Technical support and customer assistance will be provided to enhance your experience with the Service. +3. We reserve the right to modify, suspend, or discontinue any or all aspects of the Service without any obligation to you. + +**Article 2: Account Registration and Management** + +1. Prior to using the Service, registering an account is mandatory. You must ensure that the information provided at registration is accurate and updated regularly. +2. The security of your account credentials is your responsibility. Any misuse of your account should be reported to us immediately. +3. We hold the right to inspect your account and, if irregularities are detected, may halt or terminate the services provided to you. + +**Article 3: Usage Guidelines** + +1. The Service must not be used for illegal activities or in ways that infringe upon the rights of others, including intellectual property rights and confidentiality breaches. +2. The Service must not be used for malicious registration of accounts, whether for profit, speculation, or other purposes. +3. Dissemination of illegal, harmful, or malevolent content via the Service is strictly prohibited. +4. You are liable for adhering to all relevant laws and the terms of this agreement, including the responsibility for the content shared and outcomes arising from your use of the Service. + +**Article 4: Fees and Payment** + +1. You agree to the fee structure associated with the Service, as outlined in our published rates. +2. We may revise the fee structure based on market conditions, notifying you in advance. Continued use of the Service implies agreement to the revised fees. +3. Non-payment of fees may lead to the suspension or termination of the Service, and we retain the right to seek compensation. + +**Article 5: Disclaimer and Limitation of Liability** + +1. The Service is provided based on existing technology and conditions, and we do not guarantee uninterrupted, completely secure, or error-free service. +2. We are not liable for Service disruptions or unavailability due to force majeure. +3. We bear no responsibility for loss or damage of data caused by your actions. + +**Article 6: Privacy Policy** + +Your agreement to and compliance with our privacy policy, an integral part of this agreement, is required. Please refer to the detailed "Privacy Policy" section below. + +**Article 7: Intellectual Property Rights** + +1. The intellectual property of the Service and all related materials, including software and documentation, is owned by us. Unauthorized reproduction, distribution, or reverse engineering is prohibited. +2. While you retain intellectual property rights over your data and content generated within the Service, you grant us permission for necessary operations such as storage and backup to facilitate the Service. + +**Article 8: Agreement Termination** + +1. Violation of any terms of this agreement permits us to cease providing the Service immediately and to pursue legal remedies. +2. You can terminate this agreement by requesting the cancellation of your account. + +**Article 9: Dispute Resolution and Governing Law** + +1. This agreement is governed by the laws of the People's Republic of China. Disputes arising from this agreement should be resolved through negotiation; failing that, legal action may be pursued in a competent court. +2. The agreement includes provisions for resolving disputes and the applicable legal framework. + +**Article 10: Network Security** + +1. You bear the consequences for any services provided through the platform that violate national laws. +2. You are responsible for overseeing the services you offer and bear consequences for any illegal activities conducted by your users. +3. Should we discover your involvement in illegal activities, legal action will be taken and evidence provided to the authorities. + +**Article 11: Additional Provisions** + +1. Should parts of this agreement become invalid due to legal conflicts, it does not affect the validity of the remaining terms. +2. The Company retains the ultimate interpretive authority over this agreement and the privacy policy. For inquiries, please contact us. \ No newline at end of file diff --git a/docs/4.0/i18n/zh-Hans/current.json b/docs/4.0/i18n/zh-Hans/current.json index afa6ca021b8..f13c4af2f53 100644 --- a/docs/4.0/i18n/zh-Hans/current.json +++ b/docs/4.0/i18n/zh-Hans/current.json @@ -23,6 +23,10 @@ "message": "使用指南", "description": "The label for category How-to Guides in sidebar docSidebar" }, + "sidebar.docSidebar.category.Master Services Agreement": { + "message": "服务政策", + "description": "The label for category Master Services Agreement in sidebar docSidebar" + }, "sidebar.docSidebar.category.Self Hosting": { "message": "私有化部署", "description": "The label for the doc item Self Hosting in sidebar docSidebar, linking to the doc Community" diff --git a/docs/4.0/i18n/zh-Hans/msa/privacy-policy.md b/docs/4.0/i18n/zh-Hans/msa/privacy-policy.md new file mode 100644 index 00000000000..95e40288140 --- /dev/null +++ b/docs/4.0/i18n/zh-Hans/msa/privacy-policy.md @@ -0,0 +1,62 @@ +--- +sidebar_position: 2 +--- + +# Sealos 云服务隐私政策 + +我们非常重视您的隐私保护,在您使用本服务时,我们将按照以下政策收集、使用、披露和保护您的个人信息。请您仔细阅读并充分理解本隐私政策。 + +**信息收集** + +1. 在您注册或使用本服务时,我们可能收集您的姓名、电话号码、电子邮件地址、地址等个人信息。 +2. 在您使用本服务过程中产生的信息,如操作日志、访问IP地址、设备型号等。 +3. 我们可能会通过 Cookies 或其他技术收集和存储您访问本服务的相关信息,以便为您提供更好的用户体验。 + +**信息使用** + +1. 我们会根据法律法规规定以及与用户之间的约定来处理用户的个人信息。 +2. 我们可能会将收集到的信息用于改进服务质量、开发新产品或功能等目的。 +3. 我们可能会将收集到的信息用于向您推送与本服务相关的通知或广告。 + +**信息披露** + +1. 我们不会向任何第三方披露您的个人信息,除非: + + 1. 您事先同意; + + 2. 法律法规要求; + + 3. 为维护我们或其他用户的合法权益。 + +2. 我们可能与关联公司、合作伙伴分享您的个人信息,但我们会采取相应的保密措施,确保信息安全。 + +**信息保护** + +1. 我们采取各种安全措施,包括加密、访问控制等技术手段,以保护您的个人信息免受未经授权的访问、使用或泄露。 +2. 我们会定期对收集、存储和处理的个人信息进行安全评估,以确保个人信息安全。 +3. 在发生个人信息泄露等安全事件时,我们会立即启动应急预案,并在法律法规规定的范围内向您及时告知。 + +**用户权利** + +1. 您有权随时查阅、更正或删除您的个人信息。 +2. 您有权拒绝我们收集您的个人信息,但这可能导致您无法使用本服务的部分功能。 +3. 您有权要求我们停止处理您的个人信息,但这可能导致您无法继续使用本服务。 + +**隐私政策更新** + +1. 我们可能会对本隐私政策进行修改。如本隐私政策发生变更,我们将在本服务页面上发布修改后的隐私政策。如您继续使用本服务,则视为同意修改后的隐私政策。 +2. 我们鼓励您定期查阅本隐私政策,以了解我们如何保护您的个人信息。 + +**未成年人保护** + +我们非常重视对未成年人个人信息的保护,如您为未成年人,请在监护人指导下使用本服务,并请监护人帮助您在使用本服务过程中正确处理个人信息。 + +**跨境数据传输** + +由于我们的服务器可能位于不同国家或地区,您同意我们可能需要将您的个人信息传输至其他国家或地区,并在该等国家或地区存储和处理以向您提供服务。我们会采取适当措施确保跨境传输的数据仍然受到适当保护。 + +**联系我们** + +1. 如您对本隐私政策有任何疑问、建议或投诉,请通过以下方式与我们联系(微信): + [fangnux] +2. 我们将尽快回复并解决您提出的问题。 \ No newline at end of file diff --git a/docs/4.0/i18n/zh-Hans/msa/terms-of-service.md b/docs/4.0/i18n/zh-Hans/msa/terms-of-service.md new file mode 100644 index 00000000000..3d30bde57f3 --- /dev/null +++ b/docs/4.0/i18n/zh-Hans/msa/terms-of-service.md @@ -0,0 +1,68 @@ +--- +sidebar_position: 1 +--- + +# Sealos 云服务服务协议 + +Sealos 云服务服务协议是您与珠海环界云计算有限公司(以下简称“我们”或“本公司”)之间就云服务(以下简称“本服务”)的使用等相关事项所订立的协议。请您仔细阅读并充分理解本协议各条款,特别是免除或者限制我们责任的条款、对您权益的限制条款、争议解决和法律适用条款等。如您不同意本协议任一内容,请勿注册或使用本服务。 + +**第1条 服务内容** + +1. 我们将向您提供存储、计算、网络传输等基于互联网的信息技术服务。 +2. 我们将为您提供相关技术支持和客户服务,帮助您更好地使用本服务。 +3. 您同意我们有权自行决定变更、中断、终止或暂停本服务的全部或部分功能,且无需对您承担任何责任。 + +**第2条 用户注册与账户管理** + +1. 您在使用本服务前需要注册一个账户。您保证在注册时提供的信息真实、准确、完整,并及时更新。 +2. 您应妥善保管账户名和密码,对由此产生的全部行为负责。如发现他人使用您的账户,应立即通知我们。 +3. 我们有权对您的账户进行审查,如发现您的账户存在异常情况,我们有权暂停或终止向您提供服务。 + +**第3条 使用规则** + +1. 您不得利用本服务从事任何违法活动或侵犯他人合法权益的行为,包括但不限于侵犯知识产权、泄露他人商业机密等。 +2. 您不得通过任何手段恶意注册账户,包括但不限于以牟利、炒作、套现等目的。 +3. 您不得利用本服务传播任何违法、有害、恶意软件等信息。 +4. 您应遵守相关法律法规及本协议的规定,对在本服务中发布的信息及使用本服务所产生的结果承担全部责任。 + +**第4条 费用及支付** + +1. 您同意支付与本服务相关的费用,具体费用标准以我们公布的价格为准。 +2. 我们可能会根据市场情况调整费用标准,并提前通知您。您如继续使用本服务,则视为同意调整后的费用标准。 +3. 如您未按时支付费用,我们有权暂停或终止向您提供本服务,并保留追讨欠款及要求赔偿的权利。 + +**第5条 服务免责与责任限制** + +1. 本服务按照现有技术和条件所能达到的水平提供。我们不能保证本服务无故障、安全完全可靠或满足您的所有需求。 +2. 如因不可抗力导致本服务发生故障或无法正常使用,我们不承担责任。 +3. 对于因您自身原因导致的数据丢失、损坏等情况,我们不承担责任。 + +**第6条 隐私政策** + +您同意接受并遵守我们制定的隐私政策。隐私政策为本协议的一部分,具体内容请参见下文“隐私政策”。 + +**第7条 知识产权** + +1. 我们对本服务及相关软件、技术、文档等拥有全部知识产权,除非经我们明确许可,您不得进行复制、分发、出租、反向工程等行为。 +2. 您在使用本服务过程中产生的数据和内容(包括但不限于文件、图片等)之知识产权归您所有,但为了向您提供服务,您同意授权我们在必要范围内对其进行存储、备份等操作。 + +**第8条 协议终止** + +1. 如您违反本协议规定,我们有权立即终止向您提供服务,并保留追究法律责任的权利。 +2. 如您决定停止使用本服务,可以申请注销账户,本协议自账户注销之日起终止。 + +**第9条 争议解决和法律适用** + +1. 本协议的签订、履行、解释和争议解决均适用中华人民共和国法律。 +2. 若您与我们发生争议,应先友好协商解决;协商不成的,任何一方均有权将争议提交至有管辖权的人民法院诉讼解决。 + +**第10条 网络安全** + +1. 如果利用平台服务提供违反国家法律的服务,您需要自行承担后果。 +2. 您对外提供的服务需要做好监管职责,如有用户在您的服务上从事违反国家法律的行为,您需自行承担后果。 +3. 我们如果发现您存在违法行为,将会对相关部门发起诉讼,并为有关部门提供证据。 + +**第11条 其他条款** + +1. 如本协议中部分条款因违反法律法规而被视为无效,不影响其他条款的效力。 +2. 本公司保留对本协议及隐私政策的最终解释权。如您对本协议或隐私政策有任何疑问,请联系我们。 \ No newline at end of file diff --git a/docs/4.0/sidebar.json b/docs/4.0/sidebar.json index 7e6ea340012..5b5fe60b2d8 100644 --- a/docs/4.0/sidebar.json +++ b/docs/4.0/sidebar.json @@ -244,5 +244,18 @@ "type": "doc", "id": "Community", "label": "Community" + }, + { + "type": "category", + "label": "Master Services Agreement", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "autogenerated", + "dirName": "msa" + } + ] } ] \ No newline at end of file From e87219f94e2a1135fb11e2ed4ec1aebb197c23b2 Mon Sep 17 00:00:00 2001 From: Jiahui <4543bxy@gmail.com> Date: Wed, 3 Jan 2024 15:30:48 +0800 Subject: [PATCH 22/38] adapt ephemeral storage limit range (#4456) * repair calculation ratio * adapt limit range --- .../account/controllers/account_controller.go | 34 ++++++++++++------- controllers/pkg/resources/resources.go | 14 +++++--- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/controllers/account/controllers/account_controller.go b/controllers/account/controllers/account_controller.go index d32f6f608d6..718280b9dff 100644 --- a/controllers/account/controllers/account_controller.go +++ b/controllers/account/controllers/account_controller.go @@ -26,6 +26,7 @@ import ( "strings" "time" + corev1 "k8s.io/api/core/v1" "k8s.io/client-go/rest" "k8s.io/client-go/kubernetes" @@ -214,6 +215,9 @@ func (r *AccountReconciler) syncAccount(ctx context.Context, owner, accountNames if err := r.syncResourceQuotaAndLimitRange(ctx, userNamespace); err != nil { r.Logger.Error(err, "sync resource resourceQuota and limitRange failed") } + if err := r.adaptEphemeralStorageLimitRange(ctx, userNamespace); err != nil { + r.Logger.Error(err, "adapt ephemeral storage limitRange failed") + } account := accountv1.Account{ ObjectMeta: metav1.ObjectMeta{ Name: owner, @@ -298,18 +302,22 @@ func (r *AccountReconciler) syncResourceQuotaAndLimitRange(ctx context.Context, return nil } -//func (r *AccountReconciler) adaptNodePortCountQuota(ctx context.Context, nsName string) error { -// quota := resources.GetDefaultResourceQuota(nsName, ResourceQuotaPrefix+nsName) -// return retry.Retry(10, 1*time.Second, func() error { -// _, err := controllerutil.CreateOrUpdate(ctx, r.Client, quota, func() error { -// if _, ok := quota.Spec.Hard[corev1.ResourceServicesNodePorts]; !ok { -// quota.Spec.Hard[corev1.ResourceServicesNodePorts] = resource.MustParse(env.GetEnvWithDefault(resources.QuotaLimitsNodePorts, resources.DefaultQuotaLimitsNodePorts)) -// } -// return nil -// }) -// return err -// }) -//} +func (r *AccountReconciler) adaptEphemeralStorageLimitRange(ctx context.Context, nsName string) error { + limit := resources.GetDefaultLimitRange(nsName, nsName) + return retry.Retry(10, 1*time.Second, func() error { + _, err := controllerutil.CreateOrUpdate(ctx, r.Client, limit, func() error { + if len(limit.Spec.Limits) == 0 { + limit = resources.GetDefaultLimitRange(nsName, nsName) + } + limit.Spec.Limits[0].DefaultRequest[corev1.ResourceEphemeralStorage] = resources.LimitRangeDefault[corev1.ResourceEphemeralStorage] + limit.Spec.Limits[0].Default[corev1.ResourceEphemeralStorage] = resources.LimitRangeDefault[corev1.ResourceEphemeralStorage] + //if _, ok := limit.Spec.Limits[0].Default[corev1.ResourceEphemeralStorage]; !ok { + //} + return nil + }) + return err + }) +} func (r *AccountReconciler) syncRoleAndRoleBinding(ctx context.Context, name, namespace string) error { role := rbacv1.Role{ @@ -568,5 +576,5 @@ func getAmountWithDiscount(amount int64, discount pkgtypes.RechargeDiscount) int break } } - return int64(math.Ceil(float64(amount)*r)) + amount + return int64(math.Ceil(float64(amount)*r/100)) + amount } diff --git a/controllers/pkg/resources/resources.go b/controllers/pkg/resources/resources.go index 6bfd569bf62..b084ec38d16 100644 --- a/controllers/pkg/resources/resources.go +++ b/controllers/pkg/resources/resources.go @@ -487,15 +487,19 @@ func DefaultResourceQuotaHard() corev1.ResourceList { func DefaultLimitRangeLimits() []corev1.LimitRangeItem { return []corev1.LimitRangeItem{ { - Type: corev1.LimitTypeContainer, - Default: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("50m"), - corev1.ResourceMemory: resource.MustParse("64Mi"), - }, + Type: corev1.LimitTypeContainer, + Default: LimitRangeDefault, + DefaultRequest: LimitRangeDefault, }, } } +var LimitRangeDefault = corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("100Mi"), +} + // //// MiB //func GetInfraCPUQuantity(flavor string, count int) *resource.Quantity { From 07fdde5bb10e01befc3283b982975bc5c0b9b7c4 Mon Sep 17 00:00:00 2001 From: Jiahui <4543bxy@gmail.com> Date: Wed, 3 Jan 2024 15:35:02 +0800 Subject: [PATCH 23/38] k3s support version doc (#4455) --- .../quick-start/deploy-kubernetes.md | 32 ++++++++++++------- .../quick-start/deploy-kubernetes.md | 9 ++++++ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/docs/4.0/docs/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md b/docs/4.0/docs/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md index b70736a8a66..33e9fae843b 100644 --- a/docs/4.0/docs/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md +++ b/docs/4.0/docs/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md @@ -156,12 +156,13 @@ $ sealos run kubernetes.tar It's advised to use Containerd as the container runtime interface (CRI) in Kubernetes clusters. Containerd stands out for its lightweight structure and high efficiency, and it's fully compatible with Docker. Kubernetes images that utilize Containerd benefit from enhanced performance and optimized resource usage. Here are the specific supported versions: -| Kubernetes Version | Required Sealos Version | CRI Version | Cluster Image Version | -| ------------------ | ----------------------- | ----------- | -------------------------------- | -| `<1.25` | `>=v4.0.0` | v1alpha2 | labring/kubernetes:v1.24.0 | -| `>=1.25` | `>=v4.1.0` | v1alpha2 | labring/kubernetes:v1.25.0 | -| `>=1.26` | `>=v4.1.4-rc3` | v1 | labring/kubernetes:v1.26.0 | -| `>=1.27` | `>=v4.2.0-alpha3` | v1 | labring/kubernetes:v1.27.0 | +| Kubernetes Version | Required Sealos Version | CRI Version | Cluster Image Version | +| ------------------ | ----------------------- | ----------- |----------------------------| +| `<1.25` | `>=v4.0.0` | v1alpha2 | labring/kubernetes:v1.24.0 | +| `>=1.25` | `>=v4.1.0` | v1alpha2 | labring/kubernetes:v1.25.0 | +| `>=1.26` | `>=v4.1.4-rc3` | v1 | labring/kubernetes:v1.26.0 | +| `>=1.27` | `>=v4.2.0-alpha3` | v1 | labring/kubernetes:v1.27.0 | +| `>=1.28` | `>=v5.0.0` | v1 | labring/kubernetes:v1.28.0 | The choice of Sealos and CRI versions is dependent on the Kubernetes version in question. For instance, Kubernetes v1.26.0 would require Sealos v4.1.4-rc3 or newer, along with the v1 CRI version. @@ -169,12 +170,19 @@ The choice of Sealos and CRI versions is dependent on the Kubernetes version in Alternatively, Docker can also be used as the container runtime. The following table provides a breakdown of compatible Kubernetes versions with their corresponding Sealos and CRI versions for Docker-based setups: -| Kubernetes Version | Required Sealos Version | CRI Version | Cluster Image Version | -| ------------------ | ----------------------- | ----------- | -------------------------------------- | -| `<1.25` | `>=v4.0.0` | v1alpha2 | labring/kubernetes-docker:v1.24.0 | -| `>=1.25` | `>=v4.1.0` | v1alpha2 | labring/kubernetes-docker:v1.25.0 | -| `>=1.26` | `>=v4.1.4-rc3` | v1 | labring/kubernetes-docker:v1.26.0 | -| `>=1.27` | `>=v4.2.0-alpha3` | v1 | labring/kubernetes-docker:v1.27.0 | +| Kubernetes Version | Required Sealos Version | CRI Version | Cluster Image Version | +|--------------------|-------------------------| ----------- |-----------------------------------| +| `<1.25` | `>=v4.0.0` | v1alpha2 | labring/kubernetes-docker:v1.24.0 | +| `>=1.25` | `>=v4.1.0` | v1alpha2 | labring/kubernetes-docker:v1.25.0 | +| `>=1.26` | `>=v4.1.4-rc3` | v1 | labring/kubernetes-docker:v1.26.0 | +| `>=1.27` | `>=v4.2.0-alpha3` | v1 | labring/kubernetes-docker:v1.27.0 | +| `>=1.28` | `>=v5.0.0` | v1 | labring/kubernetes-docker:v1.28.0 | + +### k3s Compatibility with Containerd + +| Kubernetes Version | Required Sealos Version | Cluster Image Version | +|--------------------|-------------------------|-----------------------| +| `>=1.24` | `>=v5.0.0` | labring/k3s:v1.24.0 | As with the Containerd setup, the appropriate Sealos and CRI versions must be matched with the specific version of Kubernetes being used. For a Kubernetes v1.26.0 setup, this means selecting Sealos v4.1.4-rc3 or later, and a v1 CRI version. diff --git a/docs/4.0/i18n/zh-Hans/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md b/docs/4.0/i18n/zh-Hans/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md index 710848b50fe..83b1100f12a 100644 --- a/docs/4.0/i18n/zh-Hans/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md +++ b/docs/4.0/i18n/zh-Hans/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md @@ -162,6 +162,7 @@ $ sealos run kubernetes.tar # 单机安装,集群安装同理 | `>=1.25` | `>=v4.1.0` | v1alpha2 | labring/kubernetes:v1.25.0 | | `>=1.26` | `>=v4.1.4-rc3` | v1 | labring/kubernetes:v1.26.0 | | `>=1.27` | `>=v4.2.0-alpha3` | v1 | labring/kubernetes:v1.27.0 | +| `>=1.28` | `>=v5.0.0` | v1 | labring/kubernetes:v1.28.0 | 根据 Kubernetes 版本的不同,您可以选择不同的 Sealos 版本和 CRI 版本。例如,如果您要使用 Kubernetes v1.26.0 版本,您可以选择 sealos v4.1.4-rc3 及更高版本,并使用 v1 CRI 版本。 @@ -175,9 +176,17 @@ $ sealos run kubernetes.tar # 单机安装,集群安装同理 | `>=1.25` | `>=v4.1.0` | v1alpha2 | labring/kubernetes-docker:v1.25.0 | | `>=1.26` | `>=v4.1.4-rc3` | v1 | labring/kubernetes-docker:v1.26.0 | | `>=1.27` | `>=v4.2.0-alpha3` | v1 | labring/kubernetes-docker:v1.27.0 | +| `>=1.28` | `>=v5.0.0` | v1 | labring/kubernetes-docker:v1.28.0 | + 与支持 Containerd 的 Kubernetes 镜像类似,您可以根据 Kubernetes 版本的不同选择不同的 Sealos 版本和 CRI 版本。例如,如果您要使用 Kubernetes v1.26.0 版本,您可以选择 sealos v4.1.4-rc3 及更高版本,并使用 v1 CRI 版本。 +### 支持 Containerd 的 k3s + +| K8s 版本 | Sealos 版本 | 集群镜像版本 | +|----------|------------| --------------------------------- | +| `>=1.24` | `>=v5.0.0` | labring/kubernetes-docker:v1.24.0 | + ## 总结 您可以根据自己的需求和偏好,在不同的镜像类型和版本中进行选择。同时,不要忘记查看 [更新日志](https://github.com/labring/sealos/blob/main/CHANGELOG/CHANGELOG.md),以了解各个版本的更新内容和修复问题。 From 3c3563b12a3f34558dccff7cd555694832e49acc Mon Sep 17 00:00:00 2001 From: zhujingyang <72259332+zjy365@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:03:25 +0800 Subject: [PATCH 24/38] feat: Name modification and deployment count display (#4453) Signed-off-by: jingyang <3161362058@qq.com> --- frontend/.gitignore | 5 +- frontend/providers/template/.env.template | 4 +- .../template/public/locales/en/common.json | 10 +- .../template/public/locales/zh/common.json | 10 +- .../src/components/layout/appmenu.tsx | 8 +- .../providers/template/src/constants/keys.ts | 2 + .../src/pages/api/getTemplateSource.ts | 9 +- .../template/src/pages/api/listTemplate.ts | 1 - .../template/src/pages/api/updateRepo.ts | 38 ++++- .../src/pages/app/components/list.tsx | 86 +++++----- .../src/pages/deploy/components/Header.tsx | 58 ++++--- .../template/src/pages/deploy/index.tsx | 21 +-- .../develop/components/BreadCrumbHeader.tsx | 20 +-- .../providers/template/src/pages/index.tsx | 61 ++++--- .../src/pages/instance/components/header.tsx | 152 +++++++++++++----- .../src/services/backend/kubernetes.ts | 7 + frontend/providers/template/src/types/app.ts | 5 + .../providers/template/src/utils/adapt.ts | 12 +- .../providers/template/src/utils/json-yaml.ts | 2 +- .../providers/template/src/utils/tools.ts | 12 ++ 20 files changed, 355 insertions(+), 168 deletions(-) diff --git a/frontend/.gitignore b/frontend/.gitignore index 40b878db5b1..c92f5419545 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1 +1,4 @@ -node_modules/ \ No newline at end of file +node_modules/ +.next +.env*.local +next-env.d.ts \ No newline at end of file diff --git a/frontend/providers/template/.env.template b/frontend/providers/template/.env.template index b44b2cf47fd..eb627d53e32 100644 --- a/frontend/providers/template/.env.template +++ b/frontend/providers/template/.env.template @@ -1,4 +1,6 @@ NEXT_PUBLIC_MOCK_USER= SEALOS_CLOUD_DOMAIN= SEALOS_CERT_SECRET_NAME= -TEMPLATE_REPO_URL="https://github.com/labring-actions/templates" \ No newline at end of file +TEMPLATE_REPO_URL="https://github.com/labring-actions/templates" +# The CDN_URL environment variable is used to specify a CDN address; when set, it replaces raw.githubusercontent.com in the resource loading URL. If not set, the default address is used. +CDN_URL= \ No newline at end of file diff --git a/frontend/providers/template/public/locales/en/common.json b/frontend/providers/template/public/locales/en/common.json index 4f4f27a8017..2f446293f94 100644 --- a/frontend/providers/template/public/locales/en/common.json +++ b/frontend/providers/template/public/locales/en/common.json @@ -148,7 +148,6 @@ "Heading to sealos soon": "Heading to sealos soon", "develop": { "publish": "publish", - "YAML Detection Tool": "YAML Detection Tool", "Development": "Development", "Please enter YAML code": "Please enter YAML code", "Preview": "Preview", @@ -156,7 +155,8 @@ "YAML File": "YAML File", "Template Development": "Template Development", "Dryrun Deploy": "Dryrun Deploy", - "Formal Deploy": "Formal Deploy" + "Formal Deploy": "Formal Deploy", + "Debugging Template": "Debugging Template" }, "SideBar": { "Applications": "Applications", @@ -183,5 +183,9 @@ "Markdown Part": "Markdown Part", "Button Effect": "Button Effect", "Type": "Type", - "Deployment successful, please go to My Application to view": "Deployment successful, please go to My Application to view" + "Deployment successful, please go to My Application to view": "Deployment successful, please go to My Application to view", + "Edit": "Edit", + "Edit App Name": "Edit App Name", + "Installation Time": "Installation Time", + "users installed the app": "{{count}} users have installed the app" } \ No newline at end of file diff --git a/frontend/providers/template/public/locales/zh/common.json b/frontend/providers/template/public/locales/zh/common.json index e8ee6a2f11b..952ca177013 100644 --- a/frontend/providers/template/public/locales/zh/common.json +++ b/frontend/providers/template/public/locales/zh/common.json @@ -154,7 +154,6 @@ "Heading to sealos soon": "即将前往sealos", "develop": { "publish": "发布", - "YAML Detection Tool": "YAML 检测工具", "Development": "开发", "Please enter YAML code": "请输入yaml代码", "Preview": "预览", @@ -162,7 +161,8 @@ "YAML File": "YAML 文件", "Template Development": "模板开发", "Dryrun Deploy": "试运行部署", - "Formal Deploy": "正式部署" + "Formal Deploy": "正式部署", + "Debugging Template": "在线调试模板" }, "SideBar": { "Applications": "所有应用", @@ -189,5 +189,9 @@ "Markdown Part": "Markdown 片段", "Button Effect": "按钮效果", "Deployment successful, please go to My Application to view": "部署成功,请前往我的应用查看", - "Type": "类型" + "Type": "类型", + "Edit": "编辑", + "Edit App Name": "编辑应用名称", + "Installation Time": "安装时间", + "users installed the app": "已有 {{count}} 名用户安装应用" } \ No newline at end of file diff --git a/frontend/providers/template/src/components/layout/appmenu.tsx b/frontend/providers/template/src/components/layout/appmenu.tsx index 87ac968955c..1d7ceb19d1b 100644 --- a/frontend/providers/template/src/components/layout/appmenu.tsx +++ b/frontend/providers/template/src/components/layout/appmenu.tsx @@ -26,8 +26,7 @@ export default function AppMenu({ isMobile }: { isMobile: boolean }) { width="16" height="17" viewBox="0 0 16 17" - fill="none" - > + fill="none"> router.push('/develop')} - > + onClick={() => router.push('/develop')}> {!isMobile && ( - {t('develop.YAML Detection Tool')} + {t('develop.Debugging Template')} )} diff --git a/frontend/providers/template/src/constants/keys.ts b/frontend/providers/template/src/constants/keys.ts index ad42d1f3fd5..31845b39e75 100644 --- a/frontend/providers/template/src/constants/keys.ts +++ b/frontend/providers/template/src/constants/keys.ts @@ -10,6 +10,8 @@ export const gpuNodeSelectorKey = 'nvidia.com/gpu.product'; export const gpuResourceKey = 'nvidia.com/gpu'; // template export const templateDeployKey = 'cloud.sealos.io/deploy-on-sealos'; +export const templateDisplayNameKey = 'cloud.sealos.io/deploy-on-sealos-displayName'; + // db export const kubeblocksTypeKey = 'clusterdefinition.kubeblocks.io/name'; export const dbProviderKey = 'sealos-db-provider-cr'; diff --git a/frontend/providers/template/src/pages/api/getTemplateSource.ts b/frontend/providers/template/src/pages/api/getTemplateSource.ts index 29be8f0535e..d2df0e50ec8 100644 --- a/frontend/providers/template/src/pages/api/getTemplateSource.ts +++ b/frontend/providers/template/src/pages/api/getTemplateSource.ts @@ -63,6 +63,8 @@ export async function GetTemplateByName({ templateName: string; }) { const cdnUrl = process.env.CDN_URL; + const targetFolder = process.env.TEMPLATE_REPO_FOLDER || 'template'; + const TemplateEnvs = { SEALOS_CLOUD_DOMAIN: process.env.SEALOS_CLOUD_DOMAIN || 'cloud.sealos.io', SEALOS_CERT_SECRET_NAME: process.env.SEALOS_CERT_SECRET_NAME || 'wildcard-cert', @@ -72,13 +74,15 @@ export async function GetTemplateByName({ }; const originalPath = process.cwd(); - const targetPath = path.resolve(originalPath, 'FastDeployTemplates', 'template'); + const targetPath = path.resolve(originalPath, 'FastDeployTemplates', targetFolder); // Query by file name in template details const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json'); const jsonData: TemplateType[] = JSON.parse(fs.readFileSync(jsonPath, 'utf8')); const _tempalte = jsonData.find((item) => item.metadata.name === templateName); const _tempalteName = _tempalte ? _tempalte.spec.fileName : `${templateName}.yaml`; - const yamlString = fs.readFileSync(`${targetPath}/${_tempalteName}`, 'utf-8'); + const yamlString = _tempalte?.spec?.filePath + ? fs.readFileSync(_tempalte?.spec?.filePath, 'utf-8') + : fs.readFileSync(`${targetPath}/${_tempalteName}`, 'utf-8'); const yamlData = yaml.loadAll(yamlString); const templateYaml: TemplateType = yamlData.find( @@ -90,6 +94,7 @@ export async function GetTemplateByName({ message: 'Lack of kind template' }; } + templateYaml.spec.deployCount = _tempalte?.spec?.deployCount; if (cdnUrl) { templateYaml.spec.readme = replaceRawWithCDN(templateYaml.spec.readme, cdnUrl); templateYaml.spec.icon = replaceRawWithCDN(templateYaml.spec.icon, cdnUrl); diff --git a/frontend/providers/template/src/pages/api/listTemplate.ts b/frontend/providers/template/src/pages/api/listTemplate.ts index 16152932270..d02dcdc8749 100644 --- a/frontend/providers/template/src/pages/api/listTemplate.ts +++ b/frontend/providers/template/src/pages/api/listTemplate.ts @@ -20,7 +20,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< const originalPath = process.cwd(); const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json'); const cdnUrl = process.env.CDN_URL; - try { if (fs.existsSync(jsonPath)) { const jsonData = fs.readFileSync(jsonPath, 'utf8'); diff --git a/frontend/providers/template/src/pages/api/updateRepo.ts b/frontend/providers/template/src/pages/api/updateRepo.ts index bb0cd1e9452..787ad6be44d 100644 --- a/frontend/providers/template/src/pages/api/updateRepo.ts +++ b/frontend/providers/template/src/pages/api/updateRepo.ts @@ -1,3 +1,4 @@ +import { K8sApiDefault } from '@/services/backend/kubernetes'; import { jsonRes } from '@/services/backend/response'; import { ApiResp } from '@/services/kubernet'; import { TemplateType } from '@/types/app'; @@ -7,9 +8,10 @@ import JSYAML from 'js-yaml'; import type { NextApiRequest, NextApiResponse } from 'next'; import path from 'path'; import util from 'util'; +import * as k8s from '@kubernetes/client-node'; const execAsync = util.promisify(exec); -const readFileList = (targetPath: string, fileList: unknown[] = [], handlePath: string) => { +const readFileList = (targetPath: string, fileList: unknown[] = []) => { // fix ci const sanitizePath = (inputPath: string) => { if (typeof inputPath !== 'string') { @@ -26,16 +28,39 @@ const readFileList = (targetPath: string, fileList: unknown[] = [], handlePath: const isYamlFile = path.extname(item) === '.yaml' || path.extname(item) === '.yml'; if (stats.isFile() && isYamlFile && item !== 'template.yaml') { fileList.push(filePath); - } else if (stats.isDirectory() && item === handlePath) { - readFileList(filePath, fileList, handlePath); + } else if (stats.isDirectory()) { + readFileList(filePath, fileList); } }); }; +export async function GetTemplateStatic() { + try { + const defaultKC = K8sApiDefault(); + const result = await defaultKC + .makeApiClient(k8s.CoreV1Api) + .readNamespacedConfigMap('template-static', 'template-frontend'); + + const inputString = result?.body?.data?.['install-count'] || ''; + const installCountArray = inputString.split(/\n/).filter(Boolean); + + const temp: { [key: string]: number } = {}; + installCountArray.forEach((item) => { + const [count, name] = item.trim().split(/\s/); + temp[name] = parseInt(count, 10); + }); + return temp; + } catch (error) { + console.log(error, 'error: kubectl get configmap/template-static '); + return {}; + } +} + export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { const repoHttpUrl = process.env.TEMPLATE_REPO_URL || 'https://github.com/labring-actions/templates'; + const targetFolder = process.env.TEMPLATE_REPO_FOLDER || 'template'; const originalPath = process.cwd(); const targetPath = path.resolve(originalPath, 'FastDeployTemplates'); const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json'); @@ -60,8 +85,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< } let fileList: unknown[] = []; - readFileList(targetPath, fileList, 'template'); + const _targetPath = path.join(targetPath, targetFolder); + readFileList(_targetPath, fileList); + const templateStaticMap: { [key: string]: number } = await GetTemplateStatic(); let jsonObjArr: unknown[] = []; fileList.forEach((item: any) => { try { @@ -70,6 +97,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< const content = fs.readFileSync(item, 'utf-8'); const yamlTemplate = JSYAML.loadAll(content)[0] as TemplateType; if (!!yamlTemplate) { + const appTitle = yamlTemplate.spec.title.toUpperCase(); + yamlTemplate.spec['deployCount'] = templateStaticMap[appTitle]; + yamlTemplate.spec['filePath'] = item; yamlTemplate.spec['fileName'] = fileName; jsonObjArr.push(yamlTemplate); } diff --git a/frontend/providers/template/src/pages/app/components/list.tsx b/frontend/providers/template/src/pages/app/components/list.tsx index 82ae2db281a..631b73778ce 100644 --- a/frontend/providers/template/src/pages/app/components/list.tsx +++ b/frontend/providers/template/src/pages/app/components/list.tsx @@ -37,8 +37,7 @@ export default function InstanceList() { w={'48px'} h={'48px'} justifyContent="center" - alignItems={'center'} - > + alignItems={'center'}> @@ -52,14 +51,13 @@ export default function InstanceList() { + overflow={'auto'}> {data && data?.map((item) => { return ( @@ -73,39 +71,50 @@ export default function InstanceList() { }} key={item.id} flexDirection={'column'} - minH={'214px'} - // h="214px" p={'24px'} borderRadius={'8px'} backgroundColor={'#fff'} boxShadow={'0px 2px 4px 0px rgba(187, 196, 206, 0.25)'} - border={'1px solid #EAEBF0'} - > - - - - - {item?.id} - - - {t('Creation Time')}: {item?.createTime} - - + border={'1px solid #EAEBF0'}> + + + + + + + {item?.displayName ? item.displayName : item?.id} + + + {item?.id} + + + + + + + + + {t('Installation Time')}: {item?.createTime} + + + {/* + borderRadius={'4px'}> - {/* {t('Unload')} - */} - + + */} ); })} diff --git a/frontend/providers/template/src/pages/deploy/components/Header.tsx b/frontend/providers/template/src/pages/deploy/components/Header.tsx index ff7a529be19..af99d0f3346 100644 --- a/frontend/providers/template/src/pages/deploy/components/Header.tsx +++ b/frontend/providers/template/src/pages/deploy/components/Header.tsx @@ -1,8 +1,10 @@ import { CopyLinkIcon, HomePageIcon, HtmlIcon, MdIcon, ShareIcon } from '@/components/icons'; import { TemplateType } from '@/types/app'; import type { YamlItemType } from '@/types/index'; -import { downLoadBold, useCopyData } from '@/utils/tools'; +import { downLoadBold, formatStarNumber, useCopyData } from '@/utils/tools'; import { + Avatar, + AvatarGroup, Box, Button, Divider, @@ -18,6 +20,7 @@ import { Tooltip } from '@chakra-ui/react'; import dayjs from 'dayjs'; +import { nanoid } from 'nanoid'; import { useTranslation } from 'next-i18next'; import { MouseEvent, useCallback, useMemo } from 'react'; @@ -38,6 +41,8 @@ const Header = ({ templateDetail: TemplateType; cloudDomain: string; }) => { + console.log(templateDetail, 'templateDetail'); + const { t } = useTranslation(); const { copyData } = useCopyData(); const handleExportYaml = useCallback(async () => { @@ -74,6 +79,28 @@ const Header = ({ const HtmlPart = `Deploy on Sealos`; + const DeployCountComponent = useMemo(() => { + return ( + <> + {templateDetail?.spec?.deployCount && templateDetail?.spec?.deployCount > 6 && ( + + + + + + + + +{formatStarNumber(templateDetail.spec.deployCount)} + + + )} + + ); + }, [t, templateDetail?.spec?.deployCount]); + return ( + border={' 1px solid rgba(255, 255, 255, 0.50)'}> - + {templateDetail?.spec?.title} + {DeployCountComponent} goGithub(e, templateDetail?.spec?.gitRepo)} - > + onClick={(e) => goGithub(e, templateDetail?.spec?.gitRepo)}> {t('Home Page')} @@ -115,14 +140,12 @@ const Header = ({ + }}> {t('Share')} @@ -137,8 +160,7 @@ const Header = ({ w="60px" flexDirection={'column'} justifyContent={'center'} - alignItems={'center'} - > + alignItems={'center'}> @@ -154,8 +176,7 @@ const Header = ({ copyData(HtmlPart)} - > + onClick={() => copyData(HtmlPart)}> @@ -167,8 +188,7 @@ const Header = ({ flexDirection={'column'} alignItems={'center'} ml="auto" - onClick={() => copyData(MdPart)} - > + onClick={() => copyData(MdPart)}> @@ -195,8 +215,7 @@ const Header = ({ fontSize={'12px'} color={'5A646E'} fontWeight={400} - onClick={() => copyData(templateDetail?.spec?.description)} - > + onClick={() => copyData(templateDetail?.spec?.description)}> {templateDetail?.spec?.description}
@@ -211,8 +230,7 @@ const Header = ({ bg={'myWhite.600'} borderColor={'myGray.200'} variant={'base'} - onClick={handleExportYaml} - > + onClick={handleExportYaml}> {t('Export')} Yaml )} diff --git a/frontend/providers/template/src/pages/index.tsx b/frontend/providers/template/src/pages/index.tsx index 999368d5126..f6f956c96ba 100644 --- a/frontend/providers/template/src/pages/index.tsx +++ b/frontend/providers/template/src/pages/index.tsx @@ -4,11 +4,14 @@ import { useCachedStore } from '@/store/cached'; import { useSearchStore } from '@/store/search'; import { TemplateType } from '@/types/app'; import { serviceSideProps } from '@/utils/i18n'; -import { Box, Flex, Grid, Icon, Image, Text } from '@chakra-ui/react'; +import { Avatar, AvatarGroup, Box, Flex, Grid, Icon, Image, Text, Tooltip } from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; import { MouseEvent, useEffect, useMemo } from 'react'; +import { customAlphabet } from 'nanoid'; +import { formatStarNumber } from '@/utils/tools'; +const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'); export default function AppList() { const { t } = useTranslation(); @@ -73,15 +76,13 @@ export default function AppList() { borderRadius={'12px'} background={'linear-gradient(180deg, #FFF 0%, rgba(255, 255, 255, 0.70) 100%)'} py={'36px'} - px="42px" - > + px="42px"> + minW={'765px'}> {filterData && filterData?.map((item: TemplateType) => { return ( @@ -101,19 +102,35 @@ export default function AppList() { borderRadius={'8px'} backgroundColor={'#fff'} boxShadow={'0px 2px 4px 0px rgba(187, 196, 206, 0.25)'} - border={'1px solid #EAEBF0'} - > - - - + border={'1px solid #EAEBF0'}> + + + + + {item.spec?.deployCount && item.spec?.deployCount > 6 && ( + + + + + + + + +{formatStarNumber(item.spec.deployCount)} + + + )} + {item?.spec?.title} @@ -131,8 +148,7 @@ export default function AppList() { mt={'8px'} fontSize={'12px'} color={'5A646E'} - fontWeight={400} - > + fontWeight={400}> {item?.spec?.description} @@ -148,8 +164,7 @@ export default function AppList() { fill="#5A646E" _hover={{ fill: '#0884DD' - }} - > + }}> diff --git a/frontend/providers/template/src/pages/instance/components/header.tsx b/frontend/providers/template/src/pages/instance/components/header.tsx index a6d0cadfb8a..e2e45f6d091 100644 --- a/frontend/providers/template/src/pages/instance/components/header.tsx +++ b/frontend/providers/template/src/pages/instance/components/header.tsx @@ -1,31 +1,82 @@ +import { postDeployApp } from '@/api/app'; import { getInstanceByName } from '@/api/instance'; -import { Box, Flex, Image, Text, Icon, useDisclosure } from '@chakra-ui/react'; +import { templateDisplayNameKey } from '@/constants/keys'; +import { useToast } from '@/hooks/useToast'; +import { useResourceStore } from '@/store/resource'; +import { TemplateInstanceType } from '@/types/app'; +import { + Box, + Button, + Flex, + Icon, + Image, + Input, + Modal, + ModalCloseButton, + ModalContent, + ModalHeader, + ModalOverlay, + Text, + useDisclosure +} from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; +import JSYAML from 'js-yaml'; +import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; +import { useRef, useState } from 'react'; import DelModal from './delDodal'; -import { useTranslation } from 'next-i18next'; -import { useResourceStore } from '@/store/resource'; export default function Header({ instanceName }: { instanceName: string }) { const router = useRouter(); const { t } = useTranslation(); + const { toast } = useToast(); const { appendResource } = useResourceStore(); + const { isOpen, onOpen, onClose } = useDisclosure(); + const { + isOpen: isOpenDelModal, + onOpen: onOpenDelModal, + onClose: onCloseDelModal + } = useDisclosure(); + const [displayName, setDisplayName] = useState(''); + const yamlCR = useRef(); - const { data } = useQuery( + const { data, refetch } = useQuery( ['getInstanceByName', instanceName], () => getInstanceByName(instanceName), { onSuccess(data) { + yamlCR.current = data.yamlCR; + setDisplayName(data?.displayName || instanceName); appendResource([{ id: data.id, name: data.id, kind: 'Instance' }]); } } ); - const { - isOpen: isOpenDelModal, - onOpen: onOpenDelModal, - onClose: onCloseDelModal - } = useDisclosure(); + const handleDisplayName = async () => { + try { + if (yamlCR.current) { + yamlCR.current.metadata.labels = yamlCR.current.metadata.labels ?? {}; + if (displayName) { + yamlCR.current.metadata.labels[templateDisplayNameKey] = displayName; + } + const yaml = JSYAML.dump(yamlCR.current); + await postDeployApp([yaml], 'replace'); + refetch(); + toast({ + status: 'success', + title: 'success' + }); + } + } catch (error) { + if (typeof error === 'string') { + toast({ + status: 'error', + title: error + }); + } + } + onClose(); + }; return ( + borderBottom={'1px solid rgba(0, 0, 0, 0.07)'}> router.push('/app')} - > + onClick={() => router.push('/app')}> + border={' 1px solid rgba(255, 255, 255, 0.50)'}> - - {data?.id} - + + + + + {data?.displayName ? data?.displayName : data?.id} + + + + + + + + + {t('Edit')} + + + + + {data?.id} + + + + onClick={onOpenDelModal}> @@ -80,22 +160,22 @@ export default function Header({ instanceName }: { instanceName: string }) { {t('Unload')} - {/* - - - - - 启动 - - */} + + + + {t('Edit App Name')} + + + + {t('App Name')} + + setDisplayName(e.target.value)} /> + + + + {isOpenDelModal && ( ; }; spec: { gitRepo: string; @@ -139,4 +142,6 @@ export type InstanceListItemType = { templateType: string; title: string; url: string; + yamlCR: TemplateInstanceType; + displayName?: string; }; diff --git a/frontend/providers/template/src/utils/adapt.ts b/frontend/providers/template/src/utils/adapt.ts index 022e1a627a5..bd81d752628 100644 --- a/frontend/providers/template/src/utils/adapt.ts +++ b/frontend/providers/template/src/utils/adapt.ts @@ -1,4 +1,10 @@ -import { componentLabel, maxReplicasKey, minReplicasKey, pauseKey } from '@/constants/keys'; +import { + componentLabel, + maxReplicasKey, + minReplicasKey, + pauseKey, + templateDisplayNameKey +} from '@/constants/keys'; import { StatusEnum, StatusMap } from '@/constants/status'; import { InstanceListItemType, TemplateInstanceType } from '@/types/app'; import { AppCrdType } from '@/types/appCRD'; @@ -35,7 +41,9 @@ export function adaptInstanceListItem(item: TemplateInstanceType): InstanceListI readme: item.spec.readme, templateType: item.spec.templateType, title: item.spec.title, - url: item.spec.url + url: item.spec.url, + yamlCR: item, + displayName: item.metadata?.labels?.[templateDisplayNameKey] }; } diff --git a/frontend/providers/template/src/utils/json-yaml.ts b/frontend/providers/template/src/utils/json-yaml.ts index ecaec884bbc..2fe33446089 100644 --- a/frontend/providers/template/src/utils/json-yaml.ts +++ b/frontend/providers/template/src/utils/json-yaml.ts @@ -127,7 +127,7 @@ export const getTemplateDataSource = ( default: item.default, required: item.required, key: key, - label: key.replace('_', ' ') + label: key }; }); return inputsArr; diff --git a/frontend/providers/template/src/utils/tools.ts b/frontend/providers/template/src/utils/tools.ts index 2a8ec0b8d99..d748342ef8b 100644 --- a/frontend/providers/template/src/utils/tools.ts +++ b/frontend/providers/template/src/utils/tools.ts @@ -243,3 +243,15 @@ export function deepSearch(obj: any): string { } return 'Error'; } + +export const formatStarNumber = (number: number) => { + if (number < 1000) { + return number.toString(); + } else if (number < 10000) { + const thousands = Math.floor(number / 1000); + const remainder = number % 1000; + return `${thousands}.${remainder.toString()[0]}k`; + } else { + return (number / 1000).toFixed(1) + 'k'; + } +}; From 16b92b814a4c9628414e67ddd5ec27ad96e2ef11 Mon Sep 17 00:00:00 2001 From: zhujingyang <72259332+zjy365@users.noreply.github.com> Date: Wed, 3 Jan 2024 17:15:26 +0800 Subject: [PATCH 25/38] feat:template deploy add template-static (#4457) Signed-off-by: jingyang <3161362058@qq.com> --- .../deploy/manifests/deploy.yaml.tmpl | 51 ++++++++++++++++++- .../src/pages/app/components/list.tsx | 6 +-- .../template/src/pages/app/index.tsx | 15 +----- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/frontend/providers/template/deploy/manifests/deploy.yaml.tmpl b/frontend/providers/template/deploy/manifests/deploy.yaml.tmpl index 66a3bf191fb..a8dcf624018 100644 --- a/frontend/providers/template/deploy/manifests/deploy.yaml.tmpl +++ b/frontend/providers/template/deploy/manifests/deploy.yaml.tmpl @@ -83,4 +83,53 @@ spec: protocol: TCP targetPort: 3000 selector: - app: template-frontend \ No newline at end of file + app: template-frontend +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + namespace: template-frontend + name: template-static +spec: + schedule: "0 0 * * *" + jobTemplate: + spec: + template: + spec: + serviceAccountName: default + containers: + - name: template-static + image: bitnami/kubectl:latest + command: + - /bin/sh + - -c + - > + echo "$(kubectl get instances -A -o=jsonpath='{range .items[*]}{.spec.title}{"\n"}{end}' | tr a-z A-Z | sort | uniq -c | sort -nr | sed 's/ *//g')" > /tmp/install-count && + kubectl create configmap -n template-frontend template-static --from-file=/tmp/install-count -o yaml --dry-run=client | kubectl apply -f - + imagePullPolicy: IfNotPresent + restartPolicy: OnFailure +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: template-frontend-static-role +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update", "delete","patch"] +- apiGroups: ["app.sealos.io"] + resources: ["instances"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: template-frontend-static-role-binding +subjects: +- kind: ServiceAccount + name: default + namespace: template-frontend +roleRef: + kind: ClusterRole + name: template-frontend-static-role + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/frontend/providers/template/src/pages/app/components/list.tsx b/frontend/providers/template/src/pages/app/components/list.tsx index 631b73778ce..d1d6d37c7f2 100644 --- a/frontend/providers/template/src/pages/app/components/list.tsx +++ b/frontend/providers/template/src/pages/app/components/list.tsx @@ -88,10 +88,10 @@ export default function InstanceList() { - + {item?.displayName ? item.displayName : item?.id} - + {item?.id} @@ -110,7 +110,7 @@ export default function InstanceList() { fill="#485264" /> - + {t('Installation Time')}: {item?.createTime} diff --git a/frontend/providers/template/src/pages/app/index.tsx b/frontend/providers/template/src/pages/app/index.tsx index 33e6efa353f..d2d1100cd21 100644 --- a/frontend/providers/template/src/pages/app/index.tsx +++ b/frontend/providers/template/src/pages/app/index.tsx @@ -21,28 +21,17 @@ export default function MyApp() { borderRadius={'12px'} background={'linear-gradient(180deg, #FFF 0%, rgba(255, 255, 255, 0.70) 100%)'} pt={'36px'} - pl="42px" - > + pl="42px"> + onChange={handleTabsChange}> {t('Installed')} - {/* - 我收藏的 - */} From 972784f0047365de226cdc9ed8fcd879676eafc9 Mon Sep 17 00:00:00 2001 From: Carson Yang Date: Wed, 3 Jan 2024 18:17:51 +0800 Subject: [PATCH 26/38] docs: Add templates documentation (#4458) Signed-off-by: Carson Yang --- .../docs/guides/applaunchpad/applaunchpad.md | 125 +++++------------- .../guides/templates/images/templates.png | Bin 0 -> 181852 bytes .../docs/guides/templates/submit-template.md | 9 ++ docs/4.0/docs/guides/templates/templates.md | 13 ++ .../quick-start/install-db-with-database.md | 2 +- .../4.0/docs/quick-start/use-app-launchpad.md | 2 +- docs/4.0/docs/quick-start/use-terminal.md | 2 +- .../guides/applaunchpad/applaunchpad.md | 4 +- .../guides/templates/images/templates.png | Bin 0 -> 182062 bytes .../templates/images/wechat-qr-code.jpg | Bin 0 -> 127086 bytes .../guides/templates/submit-template.md | 37 ++++++ .../zh-Hans/guides/templates/templates.md | 13 ++ .../quick-start/install-db-with-database.md | 2 +- .../zh-Hans/quick-start/use-app-launchpad.md | 2 +- .../i18n/zh-Hans/quick-start/use-terminal.md | 2 +- 15 files changed, 111 insertions(+), 102 deletions(-) create mode 100644 docs/4.0/docs/guides/templates/images/templates.png create mode 100644 docs/4.0/docs/guides/templates/submit-template.md create mode 100644 docs/4.0/docs/guides/templates/templates.md create mode 100644 docs/4.0/i18n/zh-Hans/guides/templates/images/templates.png create mode 100644 docs/4.0/i18n/zh-Hans/guides/templates/images/wechat-qr-code.jpg create mode 100644 docs/4.0/i18n/zh-Hans/guides/templates/submit-template.md create mode 100644 docs/4.0/i18n/zh-Hans/guides/templates/templates.md diff --git a/docs/4.0/docs/guides/applaunchpad/applaunchpad.md b/docs/4.0/docs/guides/applaunchpad/applaunchpad.md index aca46b57424..4f12047ba05 100644 --- a/docs/4.0/docs/guides/applaunchpad/applaunchpad.md +++ b/docs/4.0/docs/guides/applaunchpad/applaunchpad.md @@ -4,115 +4,52 @@ sidebar_position: 1 # App Launchpad -**App Launchpad** is a single-image deployment tool offered by Sealos that can help you deploy an image online within 5 minutes. +**App Launchpad** is a feature within Sealos that serves as a single-image deployment tool. Its main goal is to streamline and expedite the process of deploying applications, allowing you to launch your application in as little as 5 minutes. -- [x] Private image -- [x] Customizable CPU and memory -- [x] Multiple replicas -- [x] HPA -- [x] External access address -- [x] Custom domains -- [x] ConfigMap configuration files -- [x] Persistent storage -- [x] APP and Pod monitoring -- [x] Logs -- [x] Events analysis -- [x] One-click entry into containers -- [x] One-click deployment to Sealos Desktop -- [x] Editable Yaml -- [x] Support for multiple external exposed ports +The tool currently boasts a range of functionalities: -## Quick Start +- Capability to deploy applications using private images. +- Flexibility to tailor CPU and memory resources according to the specific needs of the application. +- Support for deploying multiple replicas. +- Horizontal Pod Autoscaling (HPA) for dynamic scaling. +- Provision of external URLs for easy access from the public network. +- Option to assign custom domain to applications, enhancing both brand visibility and the user experience. +- Utilization of ConfigMap for configuration file management. +- Persistent storage solutions for application data, ensuring both its security and continuity. +- Real-time monitoring features for applications and Pods to facilitate prompt issue detection and resolution. +- Comprehensive logging of application activities, aiding in troubleshooting and performance optimization. +- Analysis of system events (Events) to extract critical insights for enhancing application performance. +- A convenient one-click feature to access the container terminal, simplifying management and debugging tasks. +- Ability to expose several ports of an application to the external network. -Let's take deploying a simple Nginx as an example, to demonstrate the convenience of container deployment and **App Launchpad**. +## [Quick Start](/quick-start/use-app-launchpad.md) -Complete the deployment and access in just 6 steps: +For quick and easy installation of commonly utilized applications. -1. Enter the **App Launchpad** app from the Sealos Desktop. +## [Update Application](/guides/applaunchpad/update-app.md) -![](./images/app-launchpad.jpg) +Guidance on modifying application configurations after initial deployment. -2. Click to create a new application. +## [Add a domain](/guides/applaunchpad/add-domain.md) -![](./images/app-list.png) +Instructions for integrating a custom domain with your application. -3. Turn on the **External Access** switch. The Nginx image is already filled in by default, no need for modification. Then Click Deploy Aplication. +## [Exposing Multiple Ports](/guides/applaunchpad/expose-multi-ports.md) -![](./images/app-launchpad3.png) +Details on how to make multiple ports of an application accessible externally. -4. Enter the App details. +## [Environment](/guides/applaunchpad/environment.md) -![](./images/app-launchpad4.png) +Directions for configuring applications through the use of environment variables. -5. Click the "External Address" to access Nginx. +## [ConfigMap](/guides/applaunchpad/configmap.md) -![](./images/app-launchpad6.png) +Guidelines for setting up application configurations via configuration files. -## Detailed Features +## [Autoscaling](/guides/applaunchpad/autoscale.md) -### Auto Scaling +Strategy for autoscaling the number of application instances in response to varying workloads. -You can freely switch between fixed instances or elastic scaling mode during application creation/change. +## [Persistent Volume](/guides/applaunchpad/persistent-volume.md) -![img](./images/app-launchpad7.png) - -![img](./images/app-launchpad8.png) - -- Fixed Instance: Permanently create a fixed number of Pods, unaffected by actual traffic. -- Elastic Scaling: You can choose to dynamically adjust the number of Pods based on the percentage of CPU or Memory. Setting up elastic scaling requires a certain understanding of your own business traffic. Of course, you can also directly select 1~20 instance numbers, as the billing system will only calculate the actual running instances, inactive ones will not be charged. - -### Custom Domains - -**App Launchpad** will provide you with an SSL-certified external access domain by default. Of course, when serving externally, you may wish for users to access your domain. At this time, you can set your own domain in **App Launchpad**. You'll need to make two adjustments: - -1. Fill in your own domain in the custom domain input box under the **Network Configuration** section. -2. Follow the prompt to modify the DNS at the domain service provider, CNAME resolve to the prompted domain. -3. Confirm the creation/update of the application. - -![](./images/app-launchpad9.png) - -### Environment - -**App Launchpad** uses batch input to enter environment variables, split by line, **=** sign, and **:** sign, and invalid characters in the key will be removed. - -![img](./images/app-launchpad10.png) - -**Examples of valid environment variable formats:** - -``` -makefile -host=127.0.0.1 -port:3000 -name: sealos -- username=123 -- password:123 -# Comments like this will be ignored as they don't contain = : two marking characters. -``` - -**Examples of invalid environment variable formats:** - -``` -makefile -# This line will be parsed: because it contains : or = -host=127.0.0.1 # This comment will also be parsed because there is an = sign in front of it -``` - -### ConfigMap - -You can think of ConfigMap as volumes in Docker. Mount a custom file into the container to modify container configurations. Below is an example of modifying the Nginx configuration file. - -- File Name: Corresponds to the file in the Nginx container, refer to the instructions provided by the image provider. -- File Value: Corresponds to the content of the file. If the content is too complex, you can edit it locally before pasting it here. -- Note: ConfigMap mounts individual files, not directories. - -![](./images/app-launchpad11.png) - -### Persistent Storage - -Any content saved in the Pod is temporary, so be sure not to save content that needs to be persisted directly in the Pod!!! If you want to allocate a space for persistent storage to the Pod, you can add a **Storage Volume**. - -Suppose you need to deploy a PostgreSQL database, you must create a storage volume to persistently store the content in the database. - -![](./images/app-launchpad12.png) - -Of course, we recommend you use [Database Management](./dbprovider/dbprovider.md) for deploying and managing databases. +Utilizing persistent storage for the long-term preservation of data. diff --git a/docs/4.0/docs/guides/templates/images/templates.png b/docs/4.0/docs/guides/templates/images/templates.png new file mode 100644 index 0000000000000000000000000000000000000000..ccfc2aace37cf55eb3d2e9d2dbcb6c9f52a3743d GIT binary patch literal 181852 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⁢Fe_qi5^?!}Y23pz_ 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

Q~%E6 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 Uy2)|y`yjB`+1ej0v%y~dH=Rp(v;Y7A literal 0 HcmV?d00001 diff --git a/docs/4.0/docs/guides/templates/submit-template.md b/docs/4.0/docs/guides/templates/submit-template.md new file mode 100644 index 00000000000..5fd6ebcd1d7 --- /dev/null +++ b/docs/4.0/docs/guides/templates/submit-template.md @@ -0,0 +1,9 @@ +--- +sidebar_position: 2 +--- + +# Submit template + +Every template in the Sealos template marketplace is directly and continuously updated from the [Sealos Template Repository](https://github.com/labring-actions/templates). For those interested in contributing new templates, the process involves submitting a Pull Request (PR) to this repository. + +To craft a new template, reference is available in the form of the [template.yaml](https://github.com/labring-actions/templates/blob/main/template.yaml) file. The system is equipped with a variety of common environment variables and functions that are accessible during the template development process. These integrated features enable the use of syntax akin to `GitHub Actions`. For instance, environment variables such as `${{ SEALOS_NAMESPACE }}` can be utilized to configure specific parameters in the template. Comprehensive details about these built-in environment variables are available in the [Template Guidelines](https://github.com/labring-actions/templates/blob/main/example.md). \ No newline at end of file diff --git a/docs/4.0/docs/guides/templates/templates.md b/docs/4.0/docs/guides/templates/templates.md new file mode 100644 index 00000000000..e0fb2aa8565 --- /dev/null +++ b/docs/4.0/docs/guides/templates/templates.md @@ -0,0 +1,13 @@ +--- +sidebar_position: 0 +--- + +# Templates + +Sealos's [templates](https://template.cloud.sealos.io/) offers an array of pre-designed templates, ideal for quickly setting up and launching websites and a range of applications. This marketplace hosts a variety of template types, including blogs, AI applications, low-code solutions, cloud storage, IM applications, and middleware. These templates aim to make the development process more efficient, allowing developers to rapidly initiate and deploy projects without the need to build a website from scratch or concern themselves with the intricacies of application dependencies. + +Contrasting with Vercel's template marketplace, Sealos provides a different range of applications and functionalities. Vercel primarily targets front-end project deployment, offering templates that enhance website interfaces and user interactions. However, Vercel does not offer persistent data storage, resulting in data being temporary and lost upon application restart. + +In contrast, Sealos's application templates encompass both front-end and back-end projects, along with a variety of other applications. Significantly, Sealos includes support for persistent storage, an essential aspect for applications that require extensive data storage or need to maintain data continuity. This is particularly critical for applications like e-commerce websites, large-scale social media platforms, and enterprise-level applications, where data persistence is a key requirement. + +![](./images/templates.png) \ No newline at end of file diff --git a/docs/4.0/docs/quick-start/install-db-with-database.md b/docs/4.0/docs/quick-start/install-db-with-database.md index af42f2f7ec8..af9c55890eb 100644 --- a/docs/4.0/docs/quick-start/install-db-with-database.md +++ b/docs/4.0/docs/quick-start/install-db-with-database.md @@ -4,7 +4,7 @@ sidebar_position: 4 # Use Database App -Databases are fundamental tools for data management, designed for efficient storage and access. Sealos offers a user-friendly database interface, eliminating the complexities of command-line operations. This assists in managing an array of databases, such as relational databases, NoSQL, vector databases, and streaming databases. With just a few clicks in the "[Database](../../platform-components/dbprovider/dbprovider.md)" app, you can seamlessly create a variety of databases, including MySQL, PostgreSQL, MongoDB, Redis, and many more. +Databases are fundamental tools for data management, designed for efficient storage and access. Sealos offers a user-friendly database interface, eliminating the complexities of command-line operations. This assists in managing an array of databases, such as relational databases, NoSQL, vector databases, and streaming databases. With just a few clicks in the "[Database](/guides/dbprovider/dbprovider.md)" app, you can seamlessly create a variety of databases, including MySQL, PostgreSQL, MongoDB, Redis, and many more. This guide will show you how to install MySQL use Databse app. diff --git a/docs/4.0/docs/quick-start/use-app-launchpad.md b/docs/4.0/docs/quick-start/use-app-launchpad.md index 812e0f0b12b..e5d19ee02ad 100644 --- a/docs/4.0/docs/quick-start/use-app-launchpad.md +++ b/docs/4.0/docs/quick-start/use-app-launchpad.md @@ -6,7 +6,7 @@ sidebar_position: 2 Sealos desktop is similar to that of PC operating systems, such as macOS or Windows. Each icon on the desktop represents an app, similar to the shortcuts in Windows. Like PC operating systems, Sealos also comes with built-in apps. To quickly install applications on this cloud operating system, you need to use the system's built-in **App Launchpad**. -> For more information about application management, please refer to [Introduction to App Launchpad](../../platform-components/applaunchpad/applaunchpad.md) +> For more information about application management, please refer to [Introduction to App Launchpad](/guides/applaunchpad/applaunchpad.md) This guide will show you how to quickly install some common applications on the Sealos cloud operating system. diff --git a/docs/4.0/docs/quick-start/use-terminal.md b/docs/4.0/docs/quick-start/use-terminal.md index 79308c42c33..3596109beb6 100644 --- a/docs/4.0/docs/quick-start/use-terminal.md +++ b/docs/4.0/docs/quick-start/use-terminal.md @@ -4,7 +4,7 @@ sidebar_position: 3 # Use Terminal -Users familiar with Kubernetes and container fundamentals may opt to deploy applications using the **[Terminal](../../platform-components/terminal/terminal.md)** app. This guide will show you how to use the terminal for deployment, using Nginx as an example. +Users familiar with Kubernetes and container fundamentals may opt to deploy applications using the **[Terminal](/guides/terminal/terminal.md)** app. This guide will show you how to use the terminal for deployment, using Nginx as an example. Start by launching the Terminal app within the [Sealos](https://cloud.sealos.io) desktop. diff --git a/docs/4.0/i18n/zh-Hans/guides/applaunchpad/applaunchpad.md b/docs/4.0/i18n/zh-Hans/guides/applaunchpad/applaunchpad.md index ff37b1c3cc6..558d9e3c362 100644 --- a/docs/4.0/i18n/zh-Hans/guides/applaunchpad/applaunchpad.md +++ b/docs/4.0/i18n/zh-Hans/guides/applaunchpad/applaunchpad.md @@ -1,5 +1,5 @@ --- -sidebar_position: 0 +sidebar_position: 1 --- # 应用管理 @@ -22,7 +22,7 @@ sidebar_position: 0 - 一键进入容器终端,方便管理和调试; - 支持将应用的多个端口暴露到外网。 -## [快速开始](/quick-start/app-deployments/use-app-launchpad.md) +## [快速开始](/quick-start/use-app-launchpad.md) 快速安装一些比较常见的应用。 diff --git a/docs/4.0/i18n/zh-Hans/guides/templates/images/templates.png b/docs/4.0/i18n/zh-Hans/guides/templates/images/templates.png new file mode 100644 index 0000000000000000000000000000000000000000..4e7734a645f399bea51cb8edd35b9d489a894617 GIT binary patch literal 182062 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 literal 0 HcmV?d00001 diff --git a/docs/4.0/i18n/zh-Hans/guides/templates/images/wechat-qr-code.jpg b/docs/4.0/i18n/zh-Hans/guides/templates/images/wechat-qr-code.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c842edc94e1e786144162be195a7ef414454c325 GIT binary patch literal 127086 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 literal 0 HcmV?d00001 diff --git a/docs/4.0/i18n/zh-Hans/guides/templates/submit-template.md b/docs/4.0/i18n/zh-Hans/guides/templates/submit-template.md new file mode 100644 index 00000000000..cbf9222823f --- /dev/null +++ b/docs/4.0/i18n/zh-Hans/guides/templates/submit-template.md @@ -0,0 +1,37 @@ +--- +sidebar_position: 2 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +import wechat from './images/wechat-qr-code.jpg'; + +# 提交模板 + +:::tip + +提交模板是可以拿奖金💰的!奖励规则如下: + +| 类型 | 奖金 | +| ------------------------------------------------------------ | ---- | +| 提交模板到 Sealos 模板市场 | 50¥ | +| 同时将模板的一键部署 PR 提交到模板应用的官方文档或者 README 中 | 150¥ | + +::: + +## 模板提交流程 + +Sealos 模板市场的所有模板都是实时从 [Sealos 模板仓库](https://github.com/labring-actions/templates) 同步过来的。如果您想要为这个仓库贡献新的模板,可以通过提交 PR(Pull Request)的方式来实现。 + +要创建一个新模板,您可以参考这里的 [template.yaml](https://github.com/labring-actions/templates/blob/main/template.yaml) 文件。系统已经内置了许多通用的环境变量和函数,这些都可以在编写模板时使用。这些内置的功能允许您使用类似于 `GitHub Actions` 的语法来编写模板,例如,您可以使用 `${{ SEALOS_NAMESPACE }}` 这样的环境变量来设置模板参数。关于这些内置环境变量的具体信息,可以参阅[模板说明文档](https://github.com/labring-actions/templates/blob/main/example_zh.md)。 + +## 领取奖金 + +首先填写并提交以下表单: + + + +然后扫码添加 Sealos 小助理微信领取奖金: + + \ No newline at end of file diff --git a/docs/4.0/i18n/zh-Hans/guides/templates/templates.md b/docs/4.0/i18n/zh-Hans/guides/templates/templates.md new file mode 100644 index 00000000000..fd79d5f5c71 --- /dev/null +++ b/docs/4.0/i18n/zh-Hans/guides/templates/templates.md @@ -0,0 +1,13 @@ +--- +sidebar_position: 0 +--- + +# 模板市场 + +Sealos 的[模板市场](https://template.cloud.sealos.io/)提供了一系列预制的模板,这些模板可用于快速创建和部署网站和各种应用程序。你可以在模板市场中找到各种类型的模板,比如博客、AI 应用、低代码应用、网盘、IM 应用、中间件等等。这些模板旨在简化开发过程,使开发者能够快速启动和部署项目,而无需从零开始构建整个网站,也无需关心应用之间的各种依赖关系。 + +与 Vercel 的模板市场相比,Sealos 的模板市场在应用范围和功能上有所不同。Vercel 主要专注于前端项目的部署,它的模板主要是为了支持网站的界面和用户交互部分,但它不支持数据的持久化存储,所有的数据都是临时的,一旦应用重启,数据就会丢失。 + +Sealos 应用模板不仅支持前端项目,还支持后端和其他各类应用的部署。更重要的是,Sealos 支持挂载持久化存储,这对于需要存储大量数据或者保持数据持久化的应用来说至关重要。例如,对于电商网站、大型社交媒体应用或企业级应用来说,数据的持久化是必不可少的功能。 + +![](./images/templates.png) \ No newline at end of file diff --git a/docs/4.0/i18n/zh-Hans/quick-start/install-db-with-database.md b/docs/4.0/i18n/zh-Hans/quick-start/install-db-with-database.md index f66ca9ba4a7..43f2954c0aa 100644 --- a/docs/4.0/i18n/zh-Hans/quick-start/install-db-with-database.md +++ b/docs/4.0/i18n/zh-Hans/quick-start/install-db-with-database.md @@ -4,7 +4,7 @@ sidebar_position: 4 # 安装数据库应用 -数据库是数据管理的重要手段 , 可用于高效地存储和访问数据。Sealos 提供了一个简单易用的数据库前端应用,屏蔽了繁琐的命令行操作,帮助你管理关系数据库、NoSQL、向量数据库和流数据库等各种类型的数据库。你只需通过「[数据库](../../platform-components/dbprovider/dbprovider.md)」应用就能轻松创建各种数据库,包括 MySQL、PostgreSQL、MongoDB、Redis 等多种类型的数据库。 +数据库是数据管理的重要手段 , 可用于高效地存储和访问数据。Sealos 提供了一个简单易用的数据库前端应用,屏蔽了繁琐的命令行操作,帮助你管理关系数据库、NoSQL、向量数据库和流数据库等各种类型的数据库。你只需通过「[数据库](/guides/dbprovider/dbprovider.md)」应用就能轻松创建各种数据库,包括 MySQL、PostgreSQL、MongoDB、Redis 等多种类型的数据库。 下面将通过示例来演示 Sealos 如何快速安装 MySQL。 diff --git a/docs/4.0/i18n/zh-Hans/quick-start/use-app-launchpad.md b/docs/4.0/i18n/zh-Hans/quick-start/use-app-launchpad.md index 3547fc786c0..ae96fe2ec35 100644 --- a/docs/4.0/i18n/zh-Hans/quick-start/use-app-launchpad.md +++ b/docs/4.0/i18n/zh-Hans/quick-start/use-app-launchpad.md @@ -6,7 +6,7 @@ sidebar_position: 2 Sealos 的桌面环境类似于单机操作系统 macOS 或 Windows 的桌面环境,桌面上的每个图标都是一个 App,类似于 Windows 的快捷方式。与单机操作系统一样,Sealos 也有系统自带的 App,要想在这个云操作系统中快速安装应用,就需要用到系统自带的 App:**应用管理**。 -> 关于应用管理的详细信息请参阅 [应用管理介绍](../../platform-components/applaunchpad/applaunchpad.md) +> 关于应用管理的详细信息请参阅 [应用管理介绍](/guides/applaunchpad/applaunchpad.md) 下面将演示如何在 Sealos 云操作系统中快速安装一些比较常见的应用。 diff --git a/docs/4.0/i18n/zh-Hans/quick-start/use-terminal.md b/docs/4.0/i18n/zh-Hans/quick-start/use-terminal.md index 25c37fd053d..7c510609a95 100644 --- a/docs/4.0/i18n/zh-Hans/quick-start/use-terminal.md +++ b/docs/4.0/i18n/zh-Hans/quick-start/use-terminal.md @@ -4,7 +4,7 @@ sidebar_position: 3 # 使用终端 -熟悉 Kubernetes 和容器基础知识的用户可以选择使用「[终端](../../platform-components/terminal/terminal.md)」命令行来部署应用。本文以 Nginx 为例,介绍如何使用终端来部署应用。 +熟悉 Kubernetes 和容器基础知识的用户可以选择使用「[终端](/guides/terminal/terminal.md)」命令行来部署应用。本文以 Nginx 为例,介绍如何使用终端来部署应用。 首先在 [Sealos](https://cloud.sealos.top) 桌面环境中打开终端 App。 From 73b12c5cf3e6251c13b1623a472d90c4b80a681f Mon Sep 17 00:00:00 2001 From: zhujingyang <72259332+zjy365@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:48:23 +0800 Subject: [PATCH 27/38] fix:dbprovider maximum storage (#4459) Signed-off-by: jingyang <3161362058@qq.com> --- .../src/pages/db/edit/components/Form.tsx | 8 ++++---- .../providers/template/src/pages/api/updateRepo.ts | 13 +++++++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/frontend/providers/dbprovider/src/pages/db/edit/components/Form.tsx b/frontend/providers/dbprovider/src/pages/db/edit/components/Form.tsx index 202bd23c08c..0417497a764 100644 --- a/frontend/providers/dbprovider/src/pages/db/edit/components/Form.tsx +++ b/frontend/providers/dbprovider/src/pages/db/edit/components/Form.tsx @@ -345,7 +345,7 @@ const Form = ({ - + diff --git a/frontend/providers/template/src/pages/api/updateRepo.ts b/frontend/providers/template/src/pages/api/updateRepo.ts index 787ad6be44d..bb9fea03fa9 100644 --- a/frontend/providers/template/src/pages/api/updateRepo.ts +++ b/frontend/providers/template/src/pages/api/updateRepo.ts @@ -42,12 +42,19 @@ export async function GetTemplateStatic() { .readNamespacedConfigMap('template-static', 'template-frontend'); const inputString = result?.body?.data?.['install-count'] || ''; + const installCountArray = inputString.split(/\n/).filter(Boolean); const temp: { [key: string]: number } = {}; installCountArray.forEach((item) => { - const [count, name] = item.trim().split(/\s/); - temp[name] = parseInt(count, 10); + const match = item.trim().match(/^(\d+)\s(.+)$/); + if (match) { + const count = match[1]; + const name = match[2]; + temp[name] = parseInt(count, 10); + } else { + console.error(`Data format error: ${item}`); + } }); return temp; } catch (error) { @@ -89,6 +96,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< readFileList(_targetPath, fileList); const templateStaticMap: { [key: string]: number } = await GetTemplateStatic(); + console.log(templateStaticMap); + let jsonObjArr: unknown[] = []; fileList.forEach((item: any) => { try { From c6e55b37dc22887d0e4d41003a40d974d73302ca Mon Sep 17 00:00:00 2001 From: Jiahui <4543bxy@gmail.com> Date: Thu, 4 Jan 2024 23:28:26 +0800 Subject: [PATCH 28/38] k3s support version doc (#4461) --- .../quick-start/deploy-kubernetes.md | 10 +++++----- .../quick-start/deploy-kubernetes.md | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/4.0/docs/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md b/docs/4.0/docs/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md index 33e9fae843b..0313c08fa44 100644 --- a/docs/4.0/docs/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md +++ b/docs/4.0/docs/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md @@ -178,13 +178,13 @@ Alternatively, Docker can also be used as the container runtime. The following t | `>=1.27` | `>=v4.2.0-alpha3` | v1 | labring/kubernetes-docker:v1.27.0 | | `>=1.28` | `>=v5.0.0` | v1 | labring/kubernetes-docker:v1.28.0 | -### k3s Compatibility with Containerd +As with the Containerd setup, the appropriate Sealos and CRI versions must be matched with the specific version of Kubernetes being used. For a Kubernetes v1.26.0 setup, this means selecting Sealos v4.1.4-rc3 or later, and a v1 CRI version. -| Kubernetes Version | Required Sealos Version | Cluster Image Version | -|--------------------|-------------------------|-----------------------| -| `>=1.24` | `>=v5.0.0` | labring/k3s:v1.24.0 | +### k3s Compatibility with Containerd -As with the Containerd setup, the appropriate Sealos and CRI versions must be matched with the specific version of Kubernetes being used. For a Kubernetes v1.26.0 setup, this means selecting Sealos v4.1.4-rc3 or later, and a v1 CRI version. +| k3s Version | Required Sealos Version | Cluster Image Version | +|-------------|-------------------------|-----------------------| +| `>=1.24` | `>=v5.0.0` | labring/k3s:v1.24.0 | ## Summary diff --git a/docs/4.0/i18n/zh-Hans/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md b/docs/4.0/i18n/zh-Hans/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md index 83b1100f12a..6d900af995a 100644 --- a/docs/4.0/i18n/zh-Hans/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md +++ b/docs/4.0/i18n/zh-Hans/self-hosting/lifecycle-management/quick-start/deploy-kubernetes.md @@ -183,9 +183,9 @@ $ sealos run kubernetes.tar # 单机安装,集群安装同理 ### 支持 Containerd 的 k3s -| K8s 版本 | Sealos 版本 | 集群镜像版本 | -|----------|------------| --------------------------------- | -| `>=1.24` | `>=v5.0.0` | labring/kubernetes-docker:v1.24.0 | +| K3s 版本 | Sealos 版本 | 集群镜像版本 | +|----------|------------|---------------------| +| `>=1.24` | `>=v5.0.0` | labring/k3s:v1.24.0 | ## 总结 From 60c481977f39e1565ff055e482913eaed15b93d2 Mon Sep 17 00:00:00 2001 From: Jiahui <4543bxy@gmail.com> Date: Fri, 5 Jan 2024 11:23:29 +0800 Subject: [PATCH 29/38] fix install cli with proxy (#4465) --- scripts/cloud/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cloud/install.sh b/scripts/cloud/install.sh index ad30899656a..87e80d0197c 100644 --- a/scripts/cloud/install.sh +++ b/scripts/cloud/install.sh @@ -233,7 +233,7 @@ init() { get_prompt "install_sealos" read -p " " installChoice if [[ "${installChoice,,}" == "y" ]]; then - local install_url="https://raw.githubusercontent.com/labring/sealos/${SEALOS_VERSION}/scripts/install.sh" + local install_url="https://raw.githubusercontent.com/labring/sealos/main/scripts/install.sh" [ -z "$proxy_prefix" ] || install_url="${proxy_prefix%/}/$install_url" curl -sfL "$install_url" | PROXY_PREFIX=$proxy_prefix sh -s "${SEALOS_VERSION}" labring/sealos else From 3935b2f1c3c92f9ed350601397d96a3237c3c8d0 Mon Sep 17 00:00:00 2001 From: yy <56745951+lingdie@users.noreply.github.com> Date: Fri, 5 Jan 2024 17:06:20 +0800 Subject: [PATCH 30/38] chore: add extra value for cilium. (#4466) Signed-off-by: yy --- scripts/cloud/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cloud/install.sh b/scripts/cloud/install.sh index 87e80d0197c..3654d96e798 100644 --- a/scripts/cloud/install.sh +++ b/scripts/cloud/install.sh @@ -616,7 +616,7 @@ loading_animation() { execute_commands() { [[ $k8s_installed == "y" ]] || (get_prompt "k8s_installation" && sealos apply -f $CLOUD_DIR/Clusterfile) command -v helm > /dev/null 2>&1 || sealos run "${image_registry}/${image_repository}/helm:v${helm_version#v:-3.12.0}" - [[ $k8s_ready == "y" ]] || (get_prompt "cilium_requirement" && sealos run "${image_registry}/${image_repository}/cilium:v${cilium_version#v:-1.12.14}") + [[ $k8s_ready == "y" ]] || (get_prompt "cilium_requirement" && sealos run "${image_registry}/${image_repository}/cilium:v${cilium_version#v:-1.12.14}" --env ExtraValues="ipam.mode=kubernetes) wait_cluster_ready sealos run "${image_registry}/${image_repository}/cert-manager:v${cert_manager_version#v:-1.8.0}" sealos run "${image_registry}/${image_repository}/openebs:v${openebs_version#v:-3.4.0}" From 5b9e9921b7d13bd79b769af52f72deb9167b5c19 Mon Sep 17 00:00:00 2001 From: yy <56745951+lingdie@users.noreply.github.com> Date: Fri, 5 Jan 2024 17:36:35 +0800 Subject: [PATCH 31/38] chore: add extra value for cilium. (#4468) Signed-off-by: yy --- scripts/cloud/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cloud/install.sh b/scripts/cloud/install.sh index 3654d96e798..2cc2dd0ed44 100644 --- a/scripts/cloud/install.sh +++ b/scripts/cloud/install.sh @@ -616,7 +616,7 @@ loading_animation() { execute_commands() { [[ $k8s_installed == "y" ]] || (get_prompt "k8s_installation" && sealos apply -f $CLOUD_DIR/Clusterfile) command -v helm > /dev/null 2>&1 || sealos run "${image_registry}/${image_repository}/helm:v${helm_version#v:-3.12.0}" - [[ $k8s_ready == "y" ]] || (get_prompt "cilium_requirement" && sealos run "${image_registry}/${image_repository}/cilium:v${cilium_version#v:-1.12.14}" --env ExtraValues="ipam.mode=kubernetes) + [[ $k8s_ready == "y" ]] || (get_prompt "cilium_requirement" && sealos run "${image_registry}/${image_repository}/cilium:v${cilium_version#v:-1.12.14}" --env ExtraValues="ipam.mode=kubernetes") wait_cluster_ready sealos run "${image_registry}/${image_repository}/cert-manager:v${cert_manager_version#v:-1.8.0}" sealos run "${image_registry}/${image_repository}/openebs:v${openebs_version#v:-3.4.0}" From fee8721f53a2a6b18d0d3a1add1babb0dc2e4b30 Mon Sep 17 00:00:00 2001 From: Carson Yang Date: Sun, 7 Jan 2024 00:02:37 +0800 Subject: [PATCH 32/38] docs: add component Highlight (#4471) Signed-off-by: Carson Yang --- README.md | 2 +- README_zh.md | 2 +- docs/4.0/docs/Intro.md | 4 ++ docs/4.0/docs/guides/templates/templates.md | 4 ++ docs/4.0/i18n/zh-Hans/Intro.md | 4 ++ .../low-code-platform/install-illacloud.md | 2 +- .../zh-Hans/guides/templates/templates.md | 4 ++ .../src/components/Highlight/index.tsx | 47 +++++++++++++++++++ 8 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 docs/website/src/components/Highlight/index.tsx diff --git a/README.md b/README.md index 7f4893ca348..e933e58646e 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ A Cloud Operating System designed for managing cloud-native applications [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Flabring%2Fsealos.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Flabring%2Fsealos?ref=badge_shield) [![codecov](https://codecov.io/gh/labring/sealos/branch/main/graph/badge.svg?token=e41ZDcj06N)](https://codecov.io/gh/labring/sealos) [![Website](https://img.shields.io/website?url=https%3A%2F%2Fpostwoman.io&logo=Postwoman)](https://sealos.io) -[![OSCS Status](https://www.oscs1024.com/platform/badge/labring/sealos.svg?size=small)](https://www.oscs1024.com/project/labring/sealos?ref=badge_small) +[![OSCS Status](https://www.oscs1024.com/platform/badge/labring/sealos.svg?size=small)](https://www.oscs1024.com/repo/labring/sealos?ref=badge_small)
diff --git a/README_zh.md b/README_zh.md index 8049ff54817..6506e4de121 100644 --- a/README_zh.md +++ b/README_zh.md @@ -18,7 +18,7 @@ [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Flabring%2Fsealos.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Flabring%2Fsealos?ref=badge_shield) [![codecov](https://codecov.io/gh/labring/sealos/branch/main/graph/badge.svg?token=e41ZDcj06N)](https://codecov.io/gh/labring/sealos) [![Website](https://img.shields.io/website?url=https%3A%2F%2Fpostwoman.io&logo=Postwoman)](https://sealos.run) -[![OSCS Status](https://www.oscs1024.com/platform/badge/labring/sealos.svg?size=small)](https://www.oscs1024.com/project/labring/sealos?ref=badge_small) +[![OSCS Status](https://www.oscs1024.com/platform/badge/labring/sealos.svg?size=small)](https://www.oscs1024.com/repo/labring/sealos?ref=badge_small)
diff --git a/docs/4.0/docs/Intro.md b/docs/4.0/docs/Intro.md index 3713b3f2d20..3278cb7a710 100644 --- a/docs/4.0/docs/Intro.md +++ b/docs/4.0/docs/Intro.md @@ -1,5 +1,9 @@ +import Highlight from '@site/src/components/Highlight' + # What is Sealos? + + The vastness and complexity of the cloud-native ecosystem undoubtedly leaves many businesses in disarray, yearning for an efficient, ready-to-use distribution, which this ecosystem sorely lacks. The cloud-native market is in dire need of a cloud operating system to further reduce barriers and costs. The advent of Sealos opens a new window for enterprises. It provides a novel choice for businesses and developers alike, necessitating only the installation of a cloud operating system, regardless of public or private cloud use. It allows various applications to operate stably and securely, tackling all sorts of dependency issues they might require. diff --git a/docs/4.0/docs/guides/templates/templates.md b/docs/4.0/docs/guides/templates/templates.md index e0fb2aa8565..ae2fec02015 100644 --- a/docs/4.0/docs/guides/templates/templates.md +++ b/docs/4.0/docs/guides/templates/templates.md @@ -4,6 +4,10 @@ sidebar_position: 0 # Templates +import Highlight from '@site/src/components/Highlight' + + + Sealos's [templates](https://template.cloud.sealos.io/) offers an array of pre-designed templates, ideal for quickly setting up and launching websites and a range of applications. This marketplace hosts a variety of template types, including blogs, AI applications, low-code solutions, cloud storage, IM applications, and middleware. These templates aim to make the development process more efficient, allowing developers to rapidly initiate and deploy projects without the need to build a website from scratch or concern themselves with the intricacies of application dependencies. Contrasting with Vercel's template marketplace, Sealos provides a different range of applications and functionalities. Vercel primarily targets front-end project deployment, offering templates that enhance website interfaces and user interactions. However, Vercel does not offer persistent data storage, resulting in data being temporary and lost upon application restart. diff --git a/docs/4.0/i18n/zh-Hans/Intro.md b/docs/4.0/i18n/zh-Hans/Intro.md index 62cc03cebae..c4ac398826e 100644 --- a/docs/4.0/i18n/zh-Hans/Intro.md +++ b/docs/4.0/i18n/zh-Hans/Intro.md @@ -1,5 +1,9 @@ +import Highlight from '@site/src/components/Highlight' + # 什么是 Sealos? + + 云原生生态之庞大与复杂,无疑让许多企业感到手足无措,这个生态依然缺乏好用的、开箱即用的发行版。在云原生市场还急需一款云操作系统以进一步降低云原生门槛与成本。 Sealos 的问世为企业开启了一扇新窗。它为企业与开发者提供了一种全新的选择,无论在公有云还是私有云中,都只需安装一个云操作系统。它能让各类应用在操作系统上稳定安全地运行,一并解决了应用所需的各种依赖问题。 diff --git a/docs/4.0/i18n/zh-Hans/examples/low-code-platform/install-illacloud.md b/docs/4.0/i18n/zh-Hans/examples/low-code-platform/install-illacloud.md index 09639388fe7..ef254bfca4a 100644 --- a/docs/4.0/i18n/zh-Hans/examples/low-code-platform/install-illacloud.md +++ b/docs/4.0/i18n/zh-Hans/examples/low-code-platform/install-illacloud.md @@ -1,6 +1,6 @@ # 快速安装 ILLA Cloud -[ILLA Cloud](https://www.illacloud.com/zh-CN) 是一个开源的低代码平台,使用户能够创建、部署和管理内部应用程序。通过 ILLA Cloud,您可以使用直观的拖放组件来灵活地构建各种应用程序,从基本的 CRUD 应用程序到更复杂的多步骤工作流程。 +[ILLA Cloud](https://www.illacloud.com/zh) 是一个开源的低代码平台,使用户能够创建、部署和管理内部应用程序。通过 ILLA Cloud,您可以使用直观的拖放组件来灵活地构建各种应用程序,从基本的 CRUD 应用程序到更复杂的多步骤工作流程。 ## 步骤 1:在 [Sealos](https://cloud.sealos.io) 桌面环境中打开 「应用管理」 应用 diff --git a/docs/4.0/i18n/zh-Hans/guides/templates/templates.md b/docs/4.0/i18n/zh-Hans/guides/templates/templates.md index fd79d5f5c71..f5dff84a1cc 100644 --- a/docs/4.0/i18n/zh-Hans/guides/templates/templates.md +++ b/docs/4.0/i18n/zh-Hans/guides/templates/templates.md @@ -4,6 +4,10 @@ sidebar_position: 0 # 模板市场 +import Highlight from '@site/src/components/Highlight' + + + Sealos 的[模板市场](https://template.cloud.sealos.io/)提供了一系列预制的模板,这些模板可用于快速创建和部署网站和各种应用程序。你可以在模板市场中找到各种类型的模板,比如博客、AI 应用、低代码应用、网盘、IM 应用、中间件等等。这些模板旨在简化开发过程,使开发者能够快速启动和部署项目,而无需从零开始构建整个网站,也无需关心应用之间的各种依赖关系。 与 Vercel 的模板市场相比,Sealos 的模板市场在应用范围和功能上有所不同。Vercel 主要专注于前端项目的部署,它的模板主要是为了支持网站的界面和用户交互部分,但它不支持数据的持久化存储,所有的数据都是临时的,一旦应用重启,数据就会丢失。 diff --git a/docs/website/src/components/Highlight/index.tsx b/docs/website/src/components/Highlight/index.tsx new file mode 100644 index 00000000000..aac0f2ccbd8 --- /dev/null +++ b/docs/website/src/components/Highlight/index.tsx @@ -0,0 +1,47 @@ +import React from 'react'; + +export default function LinkButton({ content, url }) { + return ( +

+ ); +} \ No newline at end of file From d7269a9cf9f70e9ee19479368a9104b249462b45 Mon Sep 17 00:00:00 2001 From: zhujingyang <72259332+zjy365@users.noreply.github.com> Date: Mon, 8 Jan 2024 17:16:53 +0800 Subject: [PATCH 33/38] fix:template redirection problem (#4472) * fix:template redirection problem Signed-off-by: jingyang <3161362058@qq.com> * add loading * fix db file upload --------- Signed-off-by: jingyang <3161362058@qq.com> --- frontend/desktop/src/pages/index.tsx | 5 +- frontend/desktop/src/pages/signin.tsx | 9 + .../providers/dbprovider/src/constants/db.ts | 2 +- .../dbprovider/src/pages/api/minio/upload.ts | 4 +- frontend/providers/template/.dockerignore | 6 +- frontend/providers/template/.gitignore | 4 +- .../deploy/manifests/deploy.yaml.tmpl | 2 + .../src/pages/api/getTemplateSource.ts | 4 +- .../template/src/pages/api/listTemplate.ts | 2 +- .../template/src/pages/api/updateRepo.ts | 4 +- .../src/pages/api/v1alpha/listTemplate.ts | 2 +- .../template/src/pages/develop/index.tsx | 29 +-- .../providers/template/src/pages/index.tsx | 222 ++++++++++-------- 13 files changed, 162 insertions(+), 133 deletions(-) diff --git a/frontend/desktop/src/pages/index.tsx b/frontend/desktop/src/pages/index.tsx index 6b23c4deaf3..d7dd16e9bb4 100644 --- a/frontend/desktop/src/pages/index.tsx +++ b/frontend/desktop/src/pages/index.tsx @@ -52,7 +52,10 @@ export default function Home({ sealos_cloud_domain }: { sealos_cloud_domain: str const { appkey, appQuery } = parseOpenappQuery((query?.openapp as string) || ''); // sealos_inside=true internal call if (whitelistApps.includes(appkey) && appQuery.indexOf('sealos_inside=true') === -1) { - window.open(`https://fastdeploy.${sealos_cloud_domain}/deploy?${appQuery}`, '_self'); + sessionStorage.setItem( + 'accessTemplatesNoLogin', + `https://template.${sealos_cloud_domain}/deploy?${appQuery}` + ); return; } if (appkey && typeof appQuery === 'string') setAutoLaunch(appkey, { raw: appQuery }); diff --git a/frontend/desktop/src/pages/signin.tsx b/frontend/desktop/src/pages/signin.tsx index d79457e7852..39b4b2de147 100644 --- a/frontend/desktop/src/pages/signin.tsx +++ b/frontend/desktop/src/pages/signin.tsx @@ -1,8 +1,17 @@ import SigninComponent from '@/components/signin'; import { compareFirstLanguages } from '@/utils/tools'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; +import { useEffect } from 'react'; export default function SigninPage() { + useEffect(() => { + const url = sessionStorage.getItem('accessTemplatesNoLogin'); + if (url) { + sessionStorage.clear(); + window.location.replace(url); + } + }, []); + return ; } diff --git a/frontend/providers/dbprovider/src/constants/db.ts b/frontend/providers/dbprovider/src/constants/db.ts index c342112ddde..dd664c5be02 100644 --- a/frontend/providers/dbprovider/src/constants/db.ts +++ b/frontend/providers/dbprovider/src/constants/db.ts @@ -168,7 +168,7 @@ export const DBTypeList = [ export const DBComponentNameMap = { [DBTypeEnum.postgresql]: 'postgresql', - [DBTypeEnum.mongodb]: 'mongo', + [DBTypeEnum.mongodb]: 'mongodb', [DBTypeEnum.mysql]: 'mysql', [DBTypeEnum.redis]: 'redis', [DBTypeEnum.kafka]: 'kafka', diff --git a/frontend/providers/dbprovider/src/pages/api/minio/upload.ts b/frontend/providers/dbprovider/src/pages/api/minio/upload.ts index caf351b91c0..a35b2ef8549 100644 --- a/frontend/providers/dbprovider/src/pages/api/minio/upload.ts +++ b/frontend/providers/dbprovider/src/pages/api/minio/upload.ts @@ -65,8 +65,8 @@ const upload = new UploadModel(); const minioClient = new Minio.Client({ endPoint: process.env?.MINIO_URL || 'minioapi.dev.sealos.top', - port: Number(process.env?.MINIO_PORT) || 80, - useSSL: false, + port: Number(process.env?.MINIO_PORT) || 443, + useSSL: Boolean(process.env?.MINIO_USE_SSL) || true, accessKey: process.env?.MINIO_ACCESS_KEY || 'database', secretKey: process.env?.MINIO_SECRET_KEY || 'database' }); diff --git a/frontend/providers/template/.dockerignore b/frontend/providers/template/.dockerignore index d16526bf068..fe2add7d3e0 100644 --- a/frontend/providers/template/.dockerignore +++ b/frontend/providers/template/.dockerignore @@ -5,9 +5,9 @@ npm-debug.log README.md .next .git -!./FastDeployTemplates/.git +!./templates/.git .yalc/ yalc.lock -FastDeployTemplates -fast_deploy_template.json \ No newline at end of file +templates +templates.json \ No newline at end of file diff --git a/frontend/providers/template/.gitignore b/frontend/providers/template/.gitignore index 69b6478ab58..2fcf9ab4d70 100644 --- a/frontend/providers/template/.gitignore +++ b/frontend/providers/template/.gitignore @@ -40,5 +40,5 @@ platform.json .yalc/ yalc.lock -FastDeployTemplates -fast_deploy_template.json +templates +templates.json diff --git a/frontend/providers/template/deploy/manifests/deploy.yaml.tmpl b/frontend/providers/template/deploy/manifests/deploy.yaml.tmpl index a8dcf624018..42206046736 100644 --- a/frontend/providers/template/deploy/manifests/deploy.yaml.tmpl +++ b/frontend/providers/template/deploy/manifests/deploy.yaml.tmpl @@ -91,6 +91,8 @@ metadata: namespace: template-frontend name: template-static spec: + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 schedule: "0 0 * * *" jobTemplate: spec: diff --git a/frontend/providers/template/src/pages/api/getTemplateSource.ts b/frontend/providers/template/src/pages/api/getTemplateSource.ts index d2df0e50ec8..d8ce7d50274 100644 --- a/frontend/providers/template/src/pages/api/getTemplateSource.ts +++ b/frontend/providers/template/src/pages/api/getTemplateSource.ts @@ -74,9 +74,9 @@ export async function GetTemplateByName({ }; const originalPath = process.cwd(); - const targetPath = path.resolve(originalPath, 'FastDeployTemplates', targetFolder); + const targetPath = path.resolve(originalPath, 'templates', targetFolder); // Query by file name in template details - const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json'); + const jsonPath = path.resolve(originalPath, 'templates.json'); const jsonData: TemplateType[] = JSON.parse(fs.readFileSync(jsonPath, 'utf8')); const _tempalte = jsonData.find((item) => item.metadata.name === templateName); const _tempalteName = _tempalte ? _tempalte.spec.fileName : `${templateName}.yaml`; diff --git a/frontend/providers/template/src/pages/api/listTemplate.ts b/frontend/providers/template/src/pages/api/listTemplate.ts index d02dcdc8749..af9cd429508 100644 --- a/frontend/providers/template/src/pages/api/listTemplate.ts +++ b/frontend/providers/template/src/pages/api/listTemplate.ts @@ -18,7 +18,7 @@ export function replaceRawWithCDN(url: string, cdnUrl: string) { export default async function handler(req: NextApiRequest, res: NextApiResponse) { const originalPath = process.cwd(); - const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json'); + const jsonPath = path.resolve(originalPath, 'templates.json'); const cdnUrl = process.env.CDN_URL; try { if (fs.existsSync(jsonPath)) { diff --git a/frontend/providers/template/src/pages/api/updateRepo.ts b/frontend/providers/template/src/pages/api/updateRepo.ts index bb9fea03fa9..2e466097088 100644 --- a/frontend/providers/template/src/pages/api/updateRepo.ts +++ b/frontend/providers/template/src/pages/api/updateRepo.ts @@ -69,8 +69,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< process.env.TEMPLATE_REPO_URL || 'https://github.com/labring-actions/templates'; const targetFolder = process.env.TEMPLATE_REPO_FOLDER || 'template'; const originalPath = process.cwd(); - const targetPath = path.resolve(originalPath, 'FastDeployTemplates'); - const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json'); + const targetPath = path.resolve(originalPath, 'templates'); + const jsonPath = path.resolve(originalPath, 'templates.json'); try { const timeoutPromise = new Promise((resolve, reject) => { diff --git a/frontend/providers/template/src/pages/api/v1alpha/listTemplate.ts b/frontend/providers/template/src/pages/api/v1alpha/listTemplate.ts index 013f3524e06..e271e0fff4e 100644 --- a/frontend/providers/template/src/pages/api/v1alpha/listTemplate.ts +++ b/frontend/providers/template/src/pages/api/v1alpha/listTemplate.ts @@ -7,7 +7,7 @@ import path from 'path'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { const originalPath = process.cwd(); - const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json'); + const jsonPath = path.resolve(originalPath, 'templates.json'); try { if (fs.existsSync(jsonPath)) { diff --git a/frontend/providers/template/src/pages/develop/index.tsx b/frontend/providers/template/src/pages/develop/index.tsx index 798d2dfedf9..be3a1930133 100644 --- a/frontend/providers/template/src/pages/develop/index.tsx +++ b/frontend/providers/template/src/pages/develop/index.tsx @@ -94,8 +94,10 @@ export default function Develop() { try { const result = getYamlSource(str); const defaultInputes = getTemplateDefaultValues(result); + const formInputs = formHook.getValues(); + setYamlSource(result); - const correctYamlList = generateCorrectYamlList(result, defaultInputes); + const correctYamlList = generateCorrectYamlList(result, formInputs); setYamlList(correctYamlList); } catch (error: any) { toast({ @@ -114,13 +116,9 @@ export default function Develop() { }); // watch form change, compute new yaml - useEffect( - () => - formHook.watch((data: any) => { - data && formOnchangeDebounce(data); - }).unsubscribe, - [formHook.watch] - ); + formHook.watch((data: any) => { + data && formOnchangeDebounce(data); + }); const formOnchangeDebounce = debounce((data: any) => { try { @@ -220,8 +218,7 @@ export default function Develop() { borderRadius={'8px'} overflowY={'hidden'} overflowX={'scroll'} - flex={1} - > + flex={1}> {/* left */} + borderRadius={'8px 8px 0px 0px '}> {t('develop.Development')} @@ -262,8 +258,7 @@ export default function Develop() { alignItems={'center'} backgroundColor={'#F8FAFB'} pl="42px" - borderRadius={'8px 8px 0px 0px '} - > + borderRadius={'8px 8px 0px 0px '}> {t('develop.Preview')} @@ -275,8 +270,7 @@ export default function Develop() { pt="26px" pr={{ sm: '20px', md: '60px' }} borderBottom={'1px solid #EFF0F1'} - flexDirection={'column'} - > + flexDirection={'column'}> {t('develop.Configure Form')} @@ -292,8 +286,7 @@ export default function Develop() { minW={'100px'} h={'34px'} variant={'link'} - onClick={handleExportYaml} - > + onClick={handleExportYaml}> {t('Export')} Yaml diff --git a/frontend/providers/template/src/pages/index.tsx b/frontend/providers/template/src/pages/index.tsx index f6f956c96ba..c42f2e4be1a 100644 --- a/frontend/providers/template/src/pages/index.tsx +++ b/frontend/providers/template/src/pages/index.tsx @@ -4,7 +4,18 @@ import { useCachedStore } from '@/store/cached'; import { useSearchStore } from '@/store/search'; import { TemplateType } from '@/types/app'; import { serviceSideProps } from '@/utils/i18n'; -import { Avatar, AvatarGroup, Box, Flex, Grid, Icon, Image, Text, Tooltip } from '@chakra-ui/react'; +import { + Avatar, + AvatarGroup, + Box, + Flex, + Grid, + Icon, + Image, + Spinner, + Text, + Tooltip +} from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; @@ -19,16 +30,21 @@ export default function AppList() { const { searchValue } = useSearchStore(); const { setInsideCloud, insideCloud } = useCachedStore(); - const { data: FastDeployTemplates } = useQuery(['listTemplte'], () => GET('/api/listTemplate'), { - refetchInterval: 5 * 60 * 1000, - staleTime: 5 * 60 * 1000 - }); + const { data: FastDeployTemplates, refetch } = useQuery( + ['listTemplte'], + () => GET('/api/listTemplate'), + { + refetchInterval: 5 * 60 * 1000, + staleTime: 5 * 60 * 1000 + } + ); - useQuery(['updateRepo'], () => updateRepo(), { + const { isLoading } = useQuery(['updateRepo'], () => updateRepo(), { refetchInterval: 5 * 60 * 1000, staleTime: 5 * 60 * 1000, onSettled(data) { console.log(data); + refetch(); } }); @@ -77,103 +93,109 @@ export default function AppList() { background={'linear-gradient(180deg, #FFF 0%, rgba(255, 255, 255, 0.70) 100%)'} py={'36px'} px="42px"> - - {filterData && - filterData?.map((item: TemplateType) => { - return ( - goDeploy(item?.metadata?.name)} - _hover={{ - borderColor: '#36ADEF', - boxShadow: '0px 4px 5px 0px rgba(185, 196, 205, 0.25)' - }} - key={item?.metadata?.name} - flexDirection={'column'} - minH={'214px'} - h="214px" - p={'24px'} - borderRadius={'8px'} - backgroundColor={'#fff'} - boxShadow={'0px 2px 4px 0px rgba(187, 196, 206, 0.25)'} - border={'1px solid #EAEBF0'}> - - - - - {item.spec?.deployCount && item.spec?.deployCount > 6 && ( - - - - - - - - +{formatStarNumber(item.spec.deployCount)} - - - )} - - - - {item?.spec?.title} - - + {!!FastDeployTemplates?.length ? ( + + {filterData && + filterData?.map((item: TemplateType) => { + return ( + goDeploy(item?.metadata?.name)} + _hover={{ + borderColor: '#36ADEF', + boxShadow: '0px 4px 5px 0px rgba(185, 196, 205, 0.25)' + }} + key={item?.metadata?.name} + flexDirection={'column'} + minH={'214px'} + h="214px" + p={'24px'} + borderRadius={'8px'} + backgroundColor={'#fff'} + boxShadow={'0px 2px 4px 0px rgba(187, 196, 206, 0.25)'} + border={'1px solid #EAEBF0'}> + + + + + {item.spec?.deployCount && item.spec?.deployCount > 6 && ( + + + + + + + + +{formatStarNumber(item.spec.deployCount)} + + + )} + + + + {item?.spec?.title} + + - - {item?.spec?.description} - - - - By - {item?.spec?.author} + + {item?.spec?.description} + + + + By + {item?.spec?.author} + + goGithub(e, item?.spec?.gitRepo)}> + + + + + - goGithub(e, item?.spec?.gitRepo)}> - - - - - - - ); - })} - + ); + })} + + ) : ( + + + + )} ); } From f4e61a65d1ca3373b1acd30a48f1fdb5f8f1b601 Mon Sep 17 00:00:00 2001 From: xudaotutou <13435638964@163.com> Date: Mon, 8 Jan 2024 17:56:57 +0800 Subject: [PATCH 34/38] chore(desktop): add service protocol link (#4463) --- frontend/desktop/next.config.js | 1 - frontend/desktop/src/api/platform.ts | 8 +- .../components/signin/auth/useProtocol.tsx | 2 +- .../desktop/src/components/signin/index.tsx | 28 +- frontend/desktop/src/hooks/useBonusBox.tsx | 76 ------ frontend/desktop/src/pages/_app.tsx | 10 +- .../pages/api/license/createLicenseRecord.ts | 31 --- .../src/pages/api/license/getLicenseRecord.ts | 29 -- frontend/desktop/src/pages/api/license/pay.ts | 84 ------ .../desktop/src/pages/api/license/result.ts | 32 --- .../desktop/src/pages/api/platform/getEnv.ts | 17 +- frontend/desktop/src/pages/index.tsx | 21 +- .../license/components/CurrencySymbol.tsx | 22 -- .../pages/license/components/OuterLink.tsx | 35 --- .../pages/license/components/Pagination.tsx | 118 -------- .../src/pages/license/components/Recharge.tsx | 258 ------------------ .../src/pages/license/components/Record.tsx | 123 --------- .../license/components/WechatPayment.tsx | 60 ---- frontend/desktop/src/pages/license/index.tsx | 75 ----- frontend/desktop/src/pages/signin.tsx | 7 +- frontend/desktop/src/stores/global.ts | 7 +- frontend/desktop/src/types/system.ts | 7 +- frontend/pnpm-lock.yaml | 41 ++- 23 files changed, 107 insertions(+), 985 deletions(-) delete mode 100644 frontend/desktop/src/hooks/useBonusBox.tsx delete mode 100644 frontend/desktop/src/pages/api/license/createLicenseRecord.ts delete mode 100644 frontend/desktop/src/pages/api/license/getLicenseRecord.ts delete mode 100644 frontend/desktop/src/pages/api/license/pay.ts delete mode 100644 frontend/desktop/src/pages/api/license/result.ts delete mode 100644 frontend/desktop/src/pages/license/components/CurrencySymbol.tsx delete mode 100644 frontend/desktop/src/pages/license/components/OuterLink.tsx delete mode 100644 frontend/desktop/src/pages/license/components/Pagination.tsx delete mode 100644 frontend/desktop/src/pages/license/components/Recharge.tsx delete mode 100644 frontend/desktop/src/pages/license/components/Record.tsx delete mode 100644 frontend/desktop/src/pages/license/components/WechatPayment.tsx delete mode 100644 frontend/desktop/src/pages/license/index.tsx diff --git a/frontend/desktop/next.config.js b/frontend/desktop/next.config.js index aca0b008a51..9bd4c668188 100644 --- a/frontend/desktop/next.config.js +++ b/frontend/desktop/next.config.js @@ -3,7 +3,6 @@ const path = require('path'); const runtimeCaching = require('next-pwa/cache'); const isProduction = process.env.NODE_ENV === 'production'; const { i18n } = require('./next-i18next.config'); - const withPWA = require('next-pwa')({ dest: 'public', runtimeCaching, diff --git a/frontend/desktop/src/api/platform.ts b/frontend/desktop/src/api/platform.ts index b9b4d96f430..8f2dda4060c 100644 --- a/frontend/desktop/src/api/platform.ts +++ b/frontend/desktop/src/api/platform.ts @@ -1,5 +1,5 @@ import request from '@/services/request'; -import { ApiResp } from '@/types'; +import { ApiResp, SystemConfigType, SystemEnv } from '@/types'; import { AccountCRD } from '@/types/user'; // handle baidu @@ -26,9 +26,11 @@ export const getUserAccount = () => { }; export const getSystemEnv = () => { - return request.get('/api/platform/getEnv'); + return request.get('/api/platform/getEnv'); +}; +export const getSystemConfig = () => { + return request.get('./api/system/getSystemConfig'); }; - export const getPriceBonus = () => { return request.get< any, diff --git a/frontend/desktop/src/components/signin/auth/useProtocol.tsx b/frontend/desktop/src/components/signin/auth/useProtocol.tsx index 36574dab25c..e974965e748 100644 --- a/frontend/desktop/src/components/signin/auth/useProtocol.tsx +++ b/frontend/desktop/src/components/signin/auth/useProtocol.tsx @@ -12,7 +12,7 @@ const useProtocol = ({ const { t, i18n } = useTranslation(); const [isAgree, setIsAgree] = useState(false); const [isInvalid, setIsInvalid] = useState(false); - + console.log(service_protocol, private_protocol); const Protocol = () => ( - request>('/api/platform/getEnv') - ); + const { data: platformEnv } = useQuery(['getPlatformEnv'], getSystemEnv); const { - service_protocol = '', - private_protocol = '', + service_protocol_zh = '', + private_protocol_zh = '', + service_protocol_en = '', + private_protocol_en = '', needPassword = false, needSms = false } = platformEnv?.data || {}; - const needTabs = needPassword && needSms; const disclosure = useDisclosure(); @@ -46,8 +45,19 @@ export default function SigninComponent() { const [tabIndex, setTabIndex] = useState(LoginType.NONE); const { ErrorComponent, showError } = useCustomError(); - - const { Protocol, isAgree, setIsInvalid } = useProtocol({ service_protocol, private_protocol }); + let protocol_data: Parameters[0]; + if (['zh', 'zh-Hans'].includes(i18n.language)) + protocol_data = { + service_protocol: service_protocol_zh, + private_protocol: private_protocol_zh + }; + else + protocol_data = { + service_protocol: service_protocol_en, + private_protocol: private_protocol_en + }; + console.log(protocol_data); + const { Protocol, isAgree, setIsInvalid } = useProtocol(protocol_data!); const { SmsModal, login: smsSubmit, isLoading: smsLoading } = useSms({ showError }); const { PasswordComponent, diff --git a/frontend/desktop/src/hooks/useBonusBox.tsx b/frontend/desktop/src/hooks/useBonusBox.tsx deleted file mode 100644 index 10920c7ee6d..00000000000 --- a/frontend/desktop/src/hooks/useBonusBox.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import request from '@/services/request'; -import { ApiResp } from '@/types'; -import { Flex, Text } from '@chakra-ui/react'; -import { useQuery } from '@tanstack/react-query'; -import { useCallback, useMemo, useState } from 'react'; -import CurrencySymbol from '../pages/license/components/CurrencySymbol'; - -export default function useBonusBox() { - const [selectAmountIndex, setSelectAmountIndex] = useState(0); - - const { data: bonuses, isSuccess } = useQuery( - ['bonus'], - () => - request.get< - any, - ApiResp<{ - steps: string; - ratios: string; - }> - >('/api/price/bonus'), - {} - ); - - const { ratios, steps } = useMemo(() => { - return { - ratios: (bonuses?.data?.ratios || '').split(',').map((v) => +v), - steps: (bonuses?.data?.steps || '').split(',').map((v) => +v) - }; - }, [bonuses?.data]); - - const BonusBox = useCallback( - () => ( - - {steps.map((amount, index) => ( - { - e.preventDefault(); - setSelectAmountIndex(index); - }} - > - - - - {amount} - - - - ))} - - ), - [selectAmountIndex, steps] - ); - - return { - BonusBox, - selectAmount: steps[selectAmountIndex] - }; -} diff --git a/frontend/desktop/src/pages/_app.tsx b/frontend/desktop/src/pages/_app.tsx index 23781753983..8ce314d4e50 100644 --- a/frontend/desktop/src/pages/_app.tsx +++ b/frontend/desktop/src/pages/_app.tsx @@ -2,7 +2,7 @@ import { theme } from '@/styles/chakraTheme'; import '@/styles/globals.scss'; import { getCookie } from '@/utils/cookieUtils'; import { ChakraProvider } from '@chakra-ui/react'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { Hydrate, QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { appWithTranslation, useTranslation } from 'next-i18next'; import type { AppProps } from 'next/app'; import Router from 'next/router'; @@ -36,9 +36,11 @@ const App = ({ Component, pageProps }: AppProps) => { return ( - - - + + + + + ); }; diff --git a/frontend/desktop/src/pages/api/license/createLicenseRecord.ts b/frontend/desktop/src/pages/api/license/createLicenseRecord.ts deleted file mode 100644 index 86aa73f8a32..00000000000 --- a/frontend/desktop/src/pages/api/license/createLicenseRecord.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { authSession } from '@/services/backend/auth'; -import { createLicenseRecord } from '@/services/backend/db/license'; -import { jsonRes } from '@/services/backend/response'; -import { LicensePayload } from '@/types'; -import type { NextApiRequest, NextApiResponse } from 'next'; - -export default async function handler(req: NextApiRequest, resp: NextApiResponse) { - try { - const payload = await authSession(req.headers); - if (!payload) return jsonRes(resp, { code: 401, message: 'token verify error' }); - - const { token, orderID, amount, quota, paymentMethod } = req.body as LicensePayload; - - const record = { - uid: payload.user.nsid, - amount: amount, - token: token, - orderID: orderID, - quota: quota, - paymentMethod: paymentMethod - }; - - const result = await createLicenseRecord(record); - - return jsonRes(resp, { - data: result - }); - } catch (error) { - jsonRes(resp, { code: 500, data: error }); - } -} diff --git a/frontend/desktop/src/pages/api/license/getLicenseRecord.ts b/frontend/desktop/src/pages/api/license/getLicenseRecord.ts deleted file mode 100644 index cf18b889010..00000000000 --- a/frontend/desktop/src/pages/api/license/getLicenseRecord.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { authSession } from '@/services/backend/auth'; -import { createLicenseRecord, getLicenseRecordsByUid } from '@/services/backend/db/license'; -import { jsonRes } from '@/services/backend/response'; -import { LicensePayload } from '@/types'; -import type { NextApiRequest, NextApiResponse } from 'next'; - -export default async function handler(req: NextApiRequest, resp: NextApiResponse) { - try { - const payload = await authSession(req.headers); - if (!payload) return jsonRes(resp, { code: 401, message: 'token verify error' }); - - const { page = 1, pageSize = 10 } = req.body as { - page: number; - pageSize: number; - }; - - const result = await getLicenseRecordsByUid({ - uid: payload.user.nsid, - page: page, - pageSize: pageSize - }); - - return jsonRes(resp, { - data: result - }); - } catch (error) { - jsonRes(resp, { code: 500, data: error }); - } -} diff --git a/frontend/desktop/src/pages/api/license/pay.ts b/frontend/desktop/src/pages/api/license/pay.ts deleted file mode 100644 index ad6a127550c..00000000000 --- a/frontend/desktop/src/pages/api/license/pay.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { authSession } from '@/services/backend/auth'; -import { ApplyYaml } from '@/services/backend/kubernetes/user'; -import { jsonRes } from '@/services/backend/response'; -import { LicensePaymentForm } from '@/types'; -import yaml from 'js-yaml'; -import type { NextApiRequest, NextApiResponse } from 'next'; - -export const generateLicenseCrd = (form: LicensePaymentForm) => { - const paymentCrd = { - apiVersion: 'infostream.sealos.io/v1', - kind: 'Payment', - metadata: { - name: form.paymentName, - namespace: form.namespace - }, - spec: { - userID: form.userId, - amount: form.amount, // weixin - paymentMethod: form.paymentMethod, - service: { - amt: form.quota, // Actual value - hid: form.hashID, - typ: 'account' - } - } - }; - try { - const result = yaml.dump(paymentCrd); - return result; - } catch (error) { - throw error; - } -}; - -export default async function handler(req: NextApiRequest, resp: NextApiResponse) { - try { - const payload = await authSession(req.headers); - if (!payload) return jsonRes(resp, { code: 401, message: 'token verify error' }); - - const { amount, paymentMethod, hid, quota } = req.body as { - amount: number; - paymentMethod: 'wechat' | 'stripe'; - hid: string; - quota: number; - }; - console.log(amount, quota, paymentMethod, hid); - if (!hid) { - return jsonRes(resp, { - code: 400, - message: 'Missing hid parameter' - }); - } - if (amount <= 0) { - return jsonRes(resp, { - code: 400, - message: 'Amount cannot be less than 0' - }); - } - - const paymentName = crypto.randomUUID(); - const form: LicensePaymentForm = { - namespace: payload.user.nsid, - paymentName: paymentName, - userId: payload.user.k8s_username, - amount: amount, - quota: quota, - paymentMethod: paymentMethod, - hashID: hid - }; - - const LicenseCrd = generateLicenseCrd(form); - - const res = await ApplyYaml(payload.kc, LicenseCrd); - return jsonRes(resp, { - data: { - paymentName: paymentName, - extra: res[0] - } - }); - } catch (error) { - console.log(error); - jsonRes(resp, { code: 500, data: error }); - } -} diff --git a/frontend/desktop/src/pages/api/license/result.ts b/frontend/desktop/src/pages/api/license/result.ts deleted file mode 100644 index a51198f2d9b..00000000000 --- a/frontend/desktop/src/pages/api/license/result.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { authSession } from '@/services/backend/auth'; -import { GetCRD } from '@/services/backend/kubernetes/user'; -import { jsonRes } from '@/services/backend/response'; -import type { NextApiRequest, NextApiResponse } from 'next'; - -export default async function handler(req: NextApiRequest, resp: NextApiResponse) { - try { - const payload = await authSession(req.headers); - if (!payload) return jsonRes(resp, { code: 401, message: 'token verify error' }); - - const { paymentName } = req.query as { - paymentName: string; - }; - - if (typeof paymentName !== 'string' || paymentName === '') { - return jsonRes(resp, { code: 400, message: 'payment name cannot be empty' }); - } - - const paymentM = { - group: 'infostream.sealos.io', - version: 'v1', - namespace: payload.user.nsid, - plural: 'payments' - }; - const paymentDesc = await GetCRD(payload.kc, paymentM, paymentName); - console.log(paymentDesc?.body?.status, 'payment'); - return jsonRes(resp, { data: paymentDesc?.body?.status }); - } catch (error) { - console.log(error); - jsonRes(resp, { code: 500, data: error }); - } -} diff --git a/frontend/desktop/src/pages/api/platform/getEnv.ts b/frontend/desktop/src/pages/api/platform/getEnv.ts index d7568530013..35340c57e15 100644 --- a/frontend/desktop/src/pages/api/platform/getEnv.ts +++ b/frontend/desktop/src/pages/api/platform/getEnv.ts @@ -11,34 +11,39 @@ import { enableLicense, enableRecharge } from '@/services/enable'; +import { ApiResp, SystemEnv } from '@/types'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { const wechat_client_id = process.env.WECHAT_CLIENT_ID || ''; const github_client_id = process.env.GITHUB_CLIENT_ID || ''; const google_client_id = process.env.GOOGLE_CLIENT_ID || ''; - const service_protocol = process.env.SERVICE_PROTOCOL || ''; - const private_protocol = process.env.PRIVATE_PROTOCOL || ''; + const service_protocol_zh = process.env.SERVICE_PROTOCOL_ZH || ''; + const private_protocol_zh = process.env.PRIVATE_PROTOCOL_ZH || ''; + const service_protocol_en = process.env.SERVICE_PROTOCOL_EN || ''; + const private_protocol_en = process.env.PRIVATE_PROTOCOL_EN || ''; const needGithub = enableGithub(); const needWechat = enableWechat(); const needPassword = enablePassword(); const needSms = enableSms(); const needGoogle = enableGoogle(); - const callback_url = process.env.CALLBACK_URL; + const callback_url = process.env.CALLBACK_URL || ''; const stripeEnabled = enableStripe(); const wechatEnabledRecharge = enableWechatRecharge(); const licenseEnabled = enableLicense(); const rechargeEnabled = enableRecharge(); const guideEnabled = process.env.GUIDE_ENABLED === 'true'; - jsonRes(res, { + jsonRes(res, { data: { SEALOS_CLOUD_DOMAIN: process.env.SEALOS_CLOUD_DOMAIN || 'cloud.sealos.io', wechat_client_id, github_client_id, google_client_id, callback_url, - service_protocol, - private_protocol, + service_protocol_zh, + private_protocol_zh, + service_protocol_en, + private_protocol_en, needPassword, needSms, needGithub, diff --git a/frontend/desktop/src/pages/index.tsx b/frontend/desktop/src/pages/index.tsx index d7dd16e9bb4..ad5a55d4bcd 100644 --- a/frontend/desktop/src/pages/index.tsx +++ b/frontend/desktop/src/pages/index.tsx @@ -1,21 +1,19 @@ import DesktopContent from '@/components/desktop_content'; import FloatButton from '@/components/floating_button'; import MoreApps from '@/components/more_apps'; -import request from '@/services/request'; import useAppStore from '@/stores/app'; import { useGlobalStore } from '@/stores/global'; import useSessionStore from '@/stores/session'; -import { ApiResp } from '@/types'; -import { SystemConfigType, SystemEnv } from '@/types/system'; import { parseOpenappQuery } from '@/utils/format'; import { compareFirstLanguages } from '@/utils/tools'; import { Box, useColorMode } from '@chakra-ui/react'; -import { useQuery } from '@tanstack/react-query'; +import { QueryClient, dehydrate, useQuery } from '@tanstack/react-query'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import Head from 'next/head'; import { useRouter } from 'next/router'; import Script from 'next/script'; import { createContext, useEffect, useState } from 'react'; +import { getSystemConfig, getSystemEnv } from '@/api/platform'; const destination = '/signin'; interface IMoreAppsContext { @@ -23,19 +21,14 @@ interface IMoreAppsContext { setShowMoreApps: (value: boolean) => void; } export const MoreAppsContext = createContext(null); - export default function Home({ sealos_cloud_domain }: { sealos_cloud_domain: string }) { const router = useRouter(); const { isUserLogin } = useSessionStore(); const { colorMode, toggleColorMode } = useColorMode(); const init = useAppStore((state) => state.init); const setAutoLaunch = useAppStore((state) => state.setAutoLaunch); - const { data: systemConfig } = useQuery(['getSystemConfig'], () => - request>('/api/system/getSystemConfig') - ); - const { data: platformEnv, isSuccess } = useQuery(['getPlatformEnv'], () => - request>('/api/platform/getEnv') - ); + const { data: systemConfig } = useQuery(['getSystemConfig'], getSystemConfig); + const { data: platformEnv, isSuccess } = useQuery(['getPlatformEnv'], getSystemEnv); const setEnv = useGlobalStore((s) => s.setEnv); // @ts-ignore if (isSuccess) Object.entries(platformEnv?.data!).forEach(([k, v]) => setEnv(k, v)); @@ -115,12 +108,14 @@ export async function getServerSideProps({ req, res, locales }: any) { const local = req?.cookies?.NEXT_LOCALE || compareFirstLanguages(req?.headers?.['accept-language'] || 'zh'); res.setHeader('Set-Cookie', `NEXT_LOCALE=${local}; Max-Age=2592000; Secure; SameSite=None`); - const sealos_cloud_domain = process.env.SEALOS_CLOUD_DOMAIN || 'cloud.sealos.io'; + const queryClient = new QueryClient(); + await queryClient.prefetchQuery({ queryKey: ['getPlatformEnv'], queryFn: getSystemEnv }); return { props: { ...(await serverSideTranslations(local, undefined, null, locales || [])), - sealos_cloud_domain + sealos_cloud_domain, + dehydratedState: dehydrate(queryClient) } }; } diff --git a/frontend/desktop/src/pages/license/components/CurrencySymbol.tsx b/frontend/desktop/src/pages/license/components/CurrencySymbol.tsx deleted file mode 100644 index f784def928f..00000000000 --- a/frontend/desktop/src/pages/license/components/CurrencySymbol.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Text, Icon } from '@chakra-ui/react'; -export default function currencysymbol({ - type = 'shellCoin', - ...props -}: { - type?: 'shellCoin' | 'cny' | 'usd'; -} & Pick[0], 'w' | 'h' | 'color'>) { - return type === 'shellCoin' ? ( - - - - ) : type === 'cny' ? ( - - ) : ( - $ - ); -} diff --git a/frontend/desktop/src/pages/license/components/OuterLink.tsx b/frontend/desktop/src/pages/license/components/OuterLink.tsx deleted file mode 100644 index 415ac13d707..00000000000 --- a/frontend/desktop/src/pages/license/components/OuterLink.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Flex, Img, Link } from '@chakra-ui/react'; -import { useTranslation } from 'next-i18next'; - -export default function Index({ text, href }: { text: string; href?: string }) { - const { t } = useTranslation(); - return ( - - - - - - {text} - - - ); -} diff --git a/frontend/desktop/src/pages/license/components/Pagination.tsx b/frontend/desktop/src/pages/license/components/Pagination.tsx deleted file mode 100644 index 064132bc699..00000000000 --- a/frontend/desktop/src/pages/license/components/Pagination.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { Flex, Text, Image, FlexProps, Icon, Box } from '@chakra-ui/react'; -import { useState } from 'react'; -type PaginationProps = { - totalItems: number; - itemsPerPage: number; - onPageChange: any; -}; - -export default function Pagination({ totalItems, itemsPerPage, onPageChange }: PaginationProps) { - const totalPage = Math.ceil(totalItems / itemsPerPage); - const [currentPage, setCurrentPage] = useState(1); - - const goToPage = (page: number) => { - if (page >= 1 && page <= totalPage) { - setCurrentPage(page); - onPageChange(page); - } - }; - - const handlePrevPage = () => { - goToPage(currentPage - 1); - }; - - const handleNextPage = () => { - goToPage(currentPage + 1); - }; - - const buttonStyle: FlexProps = { - justifyContent: 'center', - alignItems: 'center', - w: '24px', - h: '24px', - borderRadius: '50%' - }; - - return ( - - Total: - {totalItems} - - - - - - - goToPage(1)} - > - - - - - - - {currentPage}/{totalPage} - - - - - - - - goToPage(totalPage)} - > - - - - - - {itemsPerPage} - /Page - - ); -} diff --git a/frontend/desktop/src/pages/license/components/Recharge.tsx b/frontend/desktop/src/pages/license/components/Recharge.tsx deleted file mode 100644 index 8a7832e13c3..00000000000 --- a/frontend/desktop/src/pages/license/components/Recharge.tsx +++ /dev/null @@ -1,258 +0,0 @@ -import useBonusBox from '@/hooks/useBonusBox'; -import { useCustomToast } from '@/hooks/useCustomToast'; -import request from '@/services/request'; -import { ApiResp, LicensePayStatus, LicensePayload, Payment, SystemEnv } from '@/types'; -import { deFormatMoney } from '@/utils/format'; -import { - Button, - Checkbox, - Flex, - Image, - Link, - Modal, - ModalCloseButton, - ModalContent, - ModalHeader, - ModalOverlay, - Text, - useDisclosure -} from '@chakra-ui/react'; -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; -import { useTranslation } from 'next-i18next'; -import { useRouter } from 'next/router'; -import { useEffect, useState } from 'react'; -import WechatPayment from './WechatPayment'; - -export default function RechargeComponent() { - const { t } = useTranslation(); - const [isAgree, setIsAgree] = useState(false); - const [isInvalid, setIsInvalid] = useState(false); - const { BonusBox, selectAmount } = useBonusBox(); - const { isOpen, onOpen, onClose } = useDisclosure(); - // 整个流程跑通需要状态管理, 0 初始态, 1 创建支付单, 2 支付中, 3 支付成功 - const [complete, setComplete] = useState<0 | 1 | 2 | 3>(0); - // 0 是微信,1 是stripe - const [payType, setPayType] = useState<'wechat' | 'stripe'>('wechat'); - const [paymentName, setPaymentName] = useState(''); - const queryClient = useQueryClient(); - const { toast } = useCustomToast(); - const { query } = useRouter(); - const [hid, setHid] = useState(''); // license key - - // handle hid - useEffect(() => { - if (query?.hid && typeof query.hid === 'string') { - const decodedHid = decodeURIComponent(query.hid); - setHid(decodedHid); - } else { - toast({ - status: 'error', - title: 'Purchase Link Error', - isClosable: true, - position: 'top' - }); - } - }, []); - - const onModalClose = () => { - setComplete(0); - onClose(); - }; - - const handleWechatConfirm = () => { - if (isAgree) { - setComplete(1); - createPaymentLicense.mutate(); - onOpen(); - } else { - toast({ - status: 'error', - title: t('Please read and agree to the agreement'), - isClosable: true, - position: 'top' - }); - } - }; - - const { data: platformEnv } = useQuery(['getPlatformEnv'], () => - request>('/api/platform/getEnv') - ); - - const createPaymentLicense = useMutation( - () => - request.post>('/api/license/pay', { - amount: deFormatMoney(selectAmount), //weixin - quota: selectAmount, - paymentMethod: payType, - hid: hid - }), - { - onSuccess(data) { - console.log(data); - setPaymentName((data?.data?.paymentName as string).trim()); - setComplete(2); - }, - onError(err: any) { - toast({ - status: 'error', - title: err?.message || '', - isClosable: true, - position: 'top' - }); - setComplete(0); - } - } - ); - - const createLicenseRecord = useMutation( - (payload: LicensePayload) => - request.post('/api/license/createLicenseRecord', payload), - { - onSuccess(data) { - console.log(data); - queryClient.invalidateQueries(['getLicenseActive']); - }, - onError(err: any) { - console.log(err); - } - } - ); - - const { data } = useQuery( - ['getLicenseResult', paymentName], - () => - request>('/api/license/result', { - params: { - paymentName: paymentName - } - }), - { - refetchInterval: complete === 2 ? 1000 : false, - enabled: complete === 2 && !!paymentName, - cacheTime: 0, - staleTime: 0, - onSuccess(data) { - if (data?.data?.status === 'Completed') { - onModalClose(); - toast({ - status: 'success', - title: t('Payment Successful'), - isClosable: true, - position: 'top' - }); - createLicenseRecord.mutate({ - uid: '', - amount: deFormatMoney(selectAmount), - quota: selectAmount, - token: data.data?.token, - orderID: data?.data?.tradeNO, - paymentMethod: 'wechat' - }); - } - } - } - ); - - return ( - - - {t('Purchase License')} - - - {t('Select Amount')} - - - - { - setIsInvalid(false); - setIsAgree(e.target.checked); - }} - /> - - {t('agree policy')} - - {t('Service Agreement')} - - {t('and')} - - {t('Privacy Policy')} - - - {/* */} - - - {/* {platformEnv?.data?.stripeEnabled && ( - - )} */} - - - - - - - 充值金额 - - - - - - - ); -} diff --git a/frontend/desktop/src/pages/license/components/Record.tsx b/frontend/desktop/src/pages/license/components/Record.tsx deleted file mode 100644 index a46110992f9..00000000000 --- a/frontend/desktop/src/pages/license/components/Record.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import request from '@/services/request'; -import { ApiResp, LicenseRecord } from '@/types'; -import download from '@/utils/downloadFIle'; -import { formatMoney, getRemainingTime } from '@/utils/format'; -import { Box, Flex, Image, Text } from '@chakra-ui/react'; -import { useQuery } from '@tanstack/react-query'; -import { useTranslation } from 'next-i18next'; -import { useState } from 'react'; -import Pagination from './Pagination'; - -export default function History() { - const { t } = useTranslation(); - const [page, setPage] = useState(1); - const [pageSize, setPageSize] = useState(10); - - const { data } = useQuery(['getLicenseActive', page, pageSize], () => - request.post>( - '/api/license/getLicenseRecord', - { - page, - pageSize - } - ) - ); - - const downloadToken = (token: string) => { - const result = Buffer.from(token, 'binary').toString('base64'); - download('token.txt', result); - }; - - return ( - - - {t('Purchase History')} - - {data?.data?.records && data?.data?.records?.length > 0 ? ( - - {data?.data?.records.map((item) => ( - - - - token - - License - - token - - {formatMoney(item.amount)} - - - - {t('Remaining Time')} {getRemainingTime(item.exp)} - - - - - token - - Token - - downloadToken(item.token)} - src={'/icons/download.svg'} - w={'20px'} - h={'20px'} - alt="download" - > - - - ))} - - ) : ( - - empty - - {t('You have not purchased the License')} - - - )} - - - {}} - /> - - - ); -} diff --git a/frontend/desktop/src/pages/license/components/WechatPayment.tsx b/frontend/desktop/src/pages/license/components/WechatPayment.tsx deleted file mode 100644 index 8faacec5885..00000000000 --- a/frontend/desktop/src/pages/license/components/WechatPayment.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { Flex, Box, Text } from '@chakra-ui/react'; -import { useTranslation } from 'next-i18next'; -import { QRCodeSVG } from 'qrcode.react'; - -export default function WechatPayment(props: { - complete: number; - codeURL?: string; - tradeNO?: string; -}) { - const { t } = useTranslation(); - return ( - - - - {t('Scan with WeChat')} - - {props.complete === 2 && !!props.codeURL ? ( - - ) : ( - waiting... - )} - - - {t('Order Number')}: {props.tradeNO || ''} - - - {t('Payment Result')}:{props.complete === 3 ? t('Payment Successful') : t('In Payment')} - - - - - ); -} diff --git a/frontend/desktop/src/pages/license/index.tsx b/frontend/desktop/src/pages/license/index.tsx deleted file mode 100644 index f5830010c14..00000000000 --- a/frontend/desktop/src/pages/license/index.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import LangSelectSimple from '@/components/LangSelect/simple'; -import { Flex, Image, Text } from '@chakra-ui/react'; -import { useTranslation } from 'next-i18next'; -import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; -import RechargeComponent from './components/Recharge'; -import LicenseRecord from './components/Record'; -import { useRouter } from 'next/router'; -import request from '@/services/request'; -import { useQuery } from '@tanstack/react-query'; -import { ApiResp, SystemEnv } from '@/types'; - -export default function LicensePage() { - const { t } = useTranslation(); - const router = useRouter(); - const goHome = () => router.replace('/'); - - const { data: platformEnv } = useQuery( - ['getPlatformEnv'], - () => request>('/api/platform/getEnv'), - { - onSuccess(data) { - console.log(data.data?.licenseEnabled, 'licenseEnabled'); - if (!data.data?.licenseEnabled) { - goHome(); - } - } - } - ); - - return ( - - - logo - - Sealos - - - | {t('License Buy')} - - - - - - - - - ); -} - -export async function getServerSideProps({ req, res, locales }: any) { - const local = req?.cookies?.NEXT_LOCALE || 'zh'; - - return { - props: { - ...(await serverSideTranslations(local, undefined, null, locales || [])) - } - }; -} diff --git a/frontend/desktop/src/pages/signin.tsx b/frontend/desktop/src/pages/signin.tsx index 39b4b2de147..7c0c6966791 100644 --- a/frontend/desktop/src/pages/signin.tsx +++ b/frontend/desktop/src/pages/signin.tsx @@ -1,5 +1,7 @@ +import { getSystemEnv } from '@/api/platform'; import SigninComponent from '@/components/signin'; import { compareFirstLanguages } from '@/utils/tools'; +import { QueryClient, dehydrate } from '@tanstack/react-query'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import { useEffect } from 'react'; @@ -20,8 +22,11 @@ export async function getServerSideProps({ req, res, locales }: any) { req?.cookies?.NEXT_LOCALE || compareFirstLanguages(req?.headers?.['accept-language'] || 'zh'); res.setHeader('Set-Cookie', `NEXT_LOCALE=${local}; Max-Age=2592000; Secure; SameSite=None`); + const queryClient = new QueryClient(); + await queryClient.prefetchQuery({ queryKey: ['getPlatformEnv'], queryFn: getSystemEnv }); const props = { - ...(await serverSideTranslations(local, undefined, null, locales || [])) + ...(await serverSideTranslations(local, undefined, null, locales || [])), + dehydratedState: dehydrate(queryClient) }; return { props diff --git a/frontend/desktop/src/stores/global.ts b/frontend/desktop/src/stores/global.ts index 6b8b146d8dd..6c801326caf 100644 --- a/frontend/desktop/src/stores/global.ts +++ b/frontend/desktop/src/stores/global.ts @@ -1,7 +1,7 @@ import { create } from 'zustand'; import { persist } from 'zustand/middleware'; import { immer } from 'zustand/middleware/immer'; -import { Session, SystemEnv, sessionKey } from '@/types'; +import { SystemEnv } from '@/types'; type GlobalState = SystemEnv & { setEnv: (env: T, val: SystemEnv[T]) => void; @@ -11,6 +11,10 @@ export const useGlobalStore = create()( persist( immer((set) => ({ callback_url: '', + service_protocol_en: '', + service_protocol_zh: '', + private_protocol_en: '', + private_protocol_zh: '', github_client_id: '', google_client_id: '', wechat_client_id: '', @@ -23,6 +27,7 @@ export const useGlobalStore = create()( private_protocol: '', service_protocol: '', stripeEnabled: false, + guideEnabled: false, wechatEnabledRecharge: false, SEALOS_CLOUD_DOMAIN: 'cloud.sealos.io', rechargeEnabled: false, diff --git a/frontend/desktop/src/types/system.ts b/frontend/desktop/src/types/system.ts index 051560ba627..41761e16e61 100644 --- a/frontend/desktop/src/types/system.ts +++ b/frontend/desktop/src/types/system.ts @@ -12,8 +12,10 @@ export type LoginProps = { github_client_id: string; google_client_id: string; callback_url: string; - service_protocol: string; - private_protocol: string; + service_protocol_zh: string; + private_protocol_zh: string; + service_protocol_en: string; + private_protocol_en: string; needPassword: boolean; needSms: boolean; needGithub: boolean; @@ -27,4 +29,5 @@ export type SystemEnv = { wechatEnabledRecharge: boolean; rechargeEnabled: boolean; licenseEnabled: boolean; + guideEnabled: boolean; } & LoginProps; diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index b276bc7c3d9..5fb3166a6ab 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -4098,7 +4098,7 @@ packages: '@chakra-ui/react': 2.8.2(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.37)(framer-motion@10.16.5)(react-dom@18.2.0)(react@18.2.0) '@emotion/cache': 11.11.0 '@emotion/react': 11.11.1(@types/react@18.2.37)(react@18.2.0) - next: 13.5.6(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0) + next: 13.5.6(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 dev: false @@ -14310,6 +14310,45 @@ packages: - babel-plugin-macros dev: false + /next@13.5.6(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==} + engines: {node: '>=16.14.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + sass: + optional: true + dependencies: + '@next/env': 13.5.6 + '@swc/helpers': 0.5.2 + busboy: 1.6.0 + caniuse-lite: 1.0.30001565 + postcss: 8.4.31 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + styled-jsx: 5.1.1(@babel/core@7.23.3)(react@18.2.0) + watchpack: 2.4.0 + optionalDependencies: + '@next/swc-darwin-arm64': 13.5.6 + '@next/swc-darwin-x64': 13.5.6 + '@next/swc-linux-arm64-gnu': 13.5.6 + '@next/swc-linux-arm64-musl': 13.5.6 + '@next/swc-linux-x64-gnu': 13.5.6 + '@next/swc-linux-x64-musl': 13.5.6 + '@next/swc-win32-arm64-msvc': 13.5.6 + '@next/swc-win32-ia32-msvc': 13.5.6 + '@next/swc-win32-x64-msvc': 13.5.6 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + dev: false + /node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} dev: true From 87269b7997005ea27d0bb35a1eb0dfe234d9ab63 Mon Sep 17 00:00:00 2001 From: xudaotutou <13435638964@163.com> Date: Mon, 8 Jan 2024 17:57:24 +0800 Subject: [PATCH 35/38] feat(object-storage):add sort feature (#4464) --- .../components/icons/SortPolygonDownIcon.tsx | 8 + .../components/icons/SortPolygonUpIcon.tsx | 8 + frontend/packages/ui/src/components/index.ts | 6 +- frontend/pnpm-lock.yaml | 3 + frontend/providers/objectstorage/package.json | 1 + .../objectstorage/public/locales/en/file.json | 5 +- .../objectstorage/public/locales/zh/file.json | 5 +- .../BucketContainer/FileManager.tsx | 659 ++++++++++++------ .../components/BucketContainer/Monitor.tsx | 38 +- .../components/BucketContainer/PathLink.tsx | 2 +- .../common/modal/UploadModal/index.tsx | 2 +- .../objectstorage/src/pages/_app.tsx | 4 +- 12 files changed, 524 insertions(+), 217 deletions(-) create mode 100644 frontend/packages/ui/src/components/icons/SortPolygonDownIcon.tsx create mode 100644 frontend/packages/ui/src/components/icons/SortPolygonUpIcon.tsx diff --git a/frontend/packages/ui/src/components/icons/SortPolygonDownIcon.tsx b/frontend/packages/ui/src/components/icons/SortPolygonDownIcon.tsx new file mode 100644 index 00000000000..e8d3303328b --- /dev/null +++ b/frontend/packages/ui/src/components/icons/SortPolygonDownIcon.tsx @@ -0,0 +1,8 @@ +import { createIcon } from '@chakra-ui/react'; + +const SortPolygonUpIcon = createIcon({ + displayName: 'SortPolygonIcon', + viewBox: '0 0 7 5', + d: 'M3.33873 4.19508C3.61963 4.47761 4.07678 4.47761 4.35768 4.19508L6.63781 1.90173C7.08838 1.44854 6.76739 0.676758 6.12833 0.676758H1.56808C0.929025 0.676758 0.608031 1.44854 1.0586 1.90173L3.33873 4.19508Z' +}); +export default SortPolygonUpIcon; diff --git a/frontend/packages/ui/src/components/icons/SortPolygonUpIcon.tsx b/frontend/packages/ui/src/components/icons/SortPolygonUpIcon.tsx new file mode 100644 index 00000000000..52fe0f979ee --- /dev/null +++ b/frontend/packages/ui/src/components/icons/SortPolygonUpIcon.tsx @@ -0,0 +1,8 @@ +import { createIcon } from '@chakra-ui/react'; + +const SortPolygonUpIcon = createIcon({ + displayName: 'SortPolygonIcon', + viewBox: '0 0 7 5', + d: 'M3.33873 1.15843C3.61963 0.875901 4.07678 0.875902 4.35768 1.15843L6.63781 3.45179C7.08838 3.90497 6.76739 4.67676 6.12833 4.67676H1.56808C0.929025 4.67676 0.608031 3.90497 1.0586 3.45179L3.33873 1.15843Z' +}); +export default SortPolygonUpIcon; diff --git a/frontend/packages/ui/src/components/index.ts b/frontend/packages/ui/src/components/index.ts index 8655d9100e1..beef25da53d 100644 --- a/frontend/packages/ui/src/components/index.ts +++ b/frontend/packages/ui/src/components/index.ts @@ -40,6 +40,8 @@ import ListIcon from './icons/ListIcon'; import PortIcon from './icons/PortIcon'; import WarnIcon from './icons/WarnIcon'; import CloseIcon from './icons/CloseIcon'; +import SortPolygonUpIcon from './icons/SortPolygonUpIcon'; +import SortPolygonDownIcon from './icons/SortPolygonDownIcon'; export { YamlCode, @@ -83,5 +85,7 @@ export { WechatIcon, PortIcon, WarnIcon, - CloseIcon + CloseIcon, + SortPolygonUpIcon, + SortPolygonDownIcon }; diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 5fb3166a6ab..3308ede506d 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -1243,6 +1243,9 @@ importers: '@tanstack/react-query': specifier: ^4.35.3 version: 4.36.1(react-dom@18.2.0)(react@18.2.0) + '@tanstack/react-table': + specifier: ^8.10.7 + version: 8.10.7(react-dom@18.2.0)(react@18.2.0) axios: specifier: ^1.5.1 version: 1.6.2 diff --git a/frontend/providers/objectstorage/package.json b/frontend/providers/objectstorage/package.json index 919d0bc6db1..93f81a2f6d7 100644 --- a/frontend/providers/objectstorage/package.json +++ b/frontend/providers/objectstorage/package.json @@ -19,6 +19,7 @@ "@kubernetes/client-node": "^0.19.0", "@sealos/ui": "workspace:^", "@tanstack/react-query": "^4.35.3", + "@tanstack/react-table": "^8.10.7", "axios": "^1.5.1", "date-fns": "^2.30.0", "dayjs": "^1.11.10", diff --git a/frontend/providers/objectstorage/public/locales/en/file.json b/frontend/providers/objectstorage/public/locales/en/file.json index cedb798d439..c9757ac063f 100644 --- a/frontend/providers/objectstorage/public/locales/en/file.json +++ b/frontend/providers/objectstorage/public/locales/en/file.json @@ -20,5 +20,8 @@ "confirmDeleteFile": "Confirm to delete these files", "confirmDeleteSingleFile": "Confirm to delete the file", "searchFile": "Search File", - "selectedItems": "Selected {{count}} item" + "selectedItems": "Selected {{count}} item", + "clickToAscend": "Click to ascend", + "clickToDescend": "Click to descend", + "clickToCancelSort": "Click to cancel sorting" } diff --git a/frontend/providers/objectstorage/public/locales/zh/file.json b/frontend/providers/objectstorage/public/locales/zh/file.json index c83afe0cf22..d749c4591ff 100644 --- a/frontend/providers/objectstorage/public/locales/zh/file.json +++ b/frontend/providers/objectstorage/public/locales/zh/file.json @@ -20,5 +20,8 @@ "confirmDeleteFile": "确认要删除这些文件吗", "confirmDeleteSingleFile": "确认要删除这个文件吗", "searchFile": "搜索文件", - "selectedItems": "已选择 {{count}} 项" + "selectedItems": "已选择 {{count}} 项", + "clickToAscend": "点击升序", + "clickToDescend": "点击降序", + "clickToCancelSort": "点击取消排序" } \ No newline at end of file diff --git a/frontend/providers/objectstorage/src/components/BucketContainer/FileManager.tsx b/frontend/providers/objectstorage/src/components/BucketContainer/FileManager.tsx index 2778709c10a..f43e0192ab1 100644 --- a/frontend/providers/objectstorage/src/components/BucketContainer/FileManager.tsx +++ b/frontend/providers/objectstorage/src/components/BucketContainer/FileManager.tsx @@ -6,6 +6,7 @@ import { Box, Button, ButtonGroup, + ButtonProps, Center, Checkbox, Flex, @@ -27,10 +28,10 @@ import { Text, Th, Thead, + Tooltip, Tr, - useCheckboxGroup + VStack } from '@chakra-ui/react'; -import Fuse from 'fuse.js'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'next-i18next'; import PathLink from './PathLink'; @@ -42,9 +43,9 @@ import VisibityIcon from '../Icons/VisibilityIcon'; import LinkIcon from '../Icons/LinkIcon'; import FileIcon from '../Icons/FileIcon'; import FolderIcon from '../Icons/FolderIcon'; -import { GetObjectCommand, S3, S3Client } from '@aws-sdk/client-s3'; +import { GetObjectCommand, S3 } from '@aws-sdk/client-s3'; import { useToast } from '@/hooks/useToast'; -import { useEffect, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import ArrowDownSLineIcon from '../Icons/ArrowDownSLineIcon'; import { formatBytes, useCopyData } from '@/utils/tools'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; @@ -53,7 +54,16 @@ import DeleteFileModal from '../common/modal/DeleteFileModal'; import DeleteSingleFileModal from '../common/modal/DeleteSingleFileModal'; import StorageIcon from '../Icons/StorageIcon'; import useSessionStore from '@/store/session'; - +import { SortPolygonDownIcon, SortPolygonUpIcon } from '@sealos/ui'; +import { + SortDirection, + createColumnHelper, + useReactTable, + getCoreRowModel, + getSortedRowModel, + flexRender, + getFilteredRowModel +} from '@tanstack/react-table'; type EntryType = { LastModified?: Date; fileName: string; @@ -62,6 +72,75 @@ type EntryType = { type: string; isDir: boolean; }; + +enum SortState { + None, + Ascending, + Descending +} + +const SortButton = ({ + state, + nextState, + onClick, + children, + ...styles +}: { + state: SortDirection | false; + nextState: SortDirection | false; +} & ButtonProps) => { + const { t } = useTranslation('file'); + const map = new Map([ + [false, t('clickToCancelSort')], + ['asc', t('clickToAscend')], + ['desc', t('clickToDescend')] + ]); + return ( + + + + ); +}; +export enum TableHeaderID { + 'select' = 'select', + 'fileName' = 'fileName', + 'fileSize' = 'fileSize', + 'modifiedTime' = 'modifiedTime', + 'fileType' = 'fileType', + 'action' = 'action' +} export default function FileManager({ ...styles }: FlexProps) { const { t } = useTranslation('file'); const { t: commonT } = useTranslation('common'); @@ -74,11 +153,11 @@ export default function FileManager({ ...styles }: FlexProps) { const Prefix = prefix.length === 0 ? '' : [...prefix, ''].join('/'); const [pageStack, setpageStack] = useState([]); const [ContinuationToken, setContinuationToken] = useState(undefined); - const [searchVal, setSearchVal] = useState(''); const [MaxKeys, setMaxKeys] = useState(20); const { toast } = useToast(); const setPrefix = useOssStore((s) => s.setPrefix); const queryClient = useQueryClient(); + // sort const clearPage = () => { setpageStack([]); setContinuationToken(undefined); @@ -112,7 +191,7 @@ export default function FileManager({ ...styles }: FlexProps) { }, [objectsQuery.data, objectsQuery.isError]); // clear delete items useEffect(() => { - deleteCheckBoxGroupState.setValue([]); + table.toggleAllRowsSelected(false); }, [bucket, prefix, pageStack, ContinuationToken]); const deleteMutation = useMutation({ mutationFn: deleteObject(s3client!), @@ -160,51 +239,41 @@ export default function FileManager({ ...styles }: FlexProps) { }); } }; - const fileList: EntryType[] = [ - ...(objectsQuery.data?.Contents?.flatMap((_file) => { - const relativePath = - _file.Key?.replace(Prefix, '') - .split('/') - .filter((v) => v.trim() !== '') || []; - if (relativePath.length === 0) return []; - const fileName = relativePath[0]; - if (fileName === FolderPlaceholder) return []; - const fileNameArr = fileName.split('.'); - return [ - { - LastModified: _file.LastModified, - fileName, - Key: _file.Key!, - Size: _file.Size!, - type: fileNameArr.length > 1 ? fileNameArr.pop()! : 'plain', - isDir: false - } - ]; - }) || []), - ...(objectsQuery.data?.CommonPrefixes?.map((v) => ({ - LastModified: undefined, - Size: 0, - Key: v.Prefix || '/', - fileName: v.Prefix?.split('/') - .filter((v) => v.trim() !== '') - .pop()!, - type: 'folder', - isDir: true - })) || []) - ]; - const fuse = new Fuse(fileList, { - keys: ['fileName'] - }); - if (prefix.length > 0) - fileList.unshift({ - LastModified: undefined, - fileName: '..', - Key: [prefix, '..'].join('/'), - Size: 0, - type: 'link', - isDir: true - }); - const fuseList = fuse.search(searchVal); + const fileList: EntryType[] = useMemo( + () => [ + ...(objectsQuery.data?.Contents?.flatMap((_file) => { + const relativePath = + _file.Key?.replace(Prefix, '') + .split('/') + .filter((v) => v.trim() !== '') || []; + if (relativePath.length === 0) return []; + const fileName = relativePath[0]; + if (fileName === FolderPlaceholder) return []; + const fileNameArr = fileName.split('.'); + return [ + { + LastModified: _file.LastModified, + fileName, + Key: _file.Key!, + Size: _file.Size!, + type: fileNameArr.length > 1 ? fileNameArr.pop()! : 'plain', + isDir: false + } + ]; + }) || []), + ...(objectsQuery.data?.CommonPrefixes?.map((v) => ({ + LastModified: undefined, + Size: 0, + Key: v.Prefix || '/', + fileName: v.Prefix?.split('/') + .filter((v) => v.trim() !== '') + .pop()!, + type: 'folder', + isDir: true + })) || []) + ], + [objectsQuery.data] + ); // get url const generateUrl = async (client: S3, Bucket: string, Key: string) => { if (bucket?.policy === Authority.private) { @@ -222,11 +291,8 @@ export default function FileManager({ ...styles }: FlexProps) { return url; } }; - // -------- - // budle delete - const deleteCheckBoxGroupState = useCheckboxGroup({ - defaultValue: [] - }); + // // -------- + // // budle delete const multiDeleteEntry = async (_keyList: string[]) => { if (!s3client || !bucket?.name) return; @@ -258,17 +324,248 @@ export default function FileManager({ ...styles }: FlexProps) { Objects: fileObjs } }); - deleteCheckBoxGroupState.setValue([]); }; - - const trueFileList = fileList.filter( - (f) => !((f.fileName === '..' && f.isDir) || f.fileName === FolderPlaceholder) - ); - const allDelete = - trueFileList.length > 0 && - trueFileList.every((f) => deleteCheckBoxGroupState.value.includes(f.Key)); - const someDelete = - trueFileList.some((f) => deleteCheckBoxGroupState.value.includes(f.Key)) && !allDelete; + const columns = useMemo(() => { + const columnHelper = createColumnHelper(); + return [ + columnHelper.display({ + enablePinning: true, + id: TableHeaderID.select, + header({ table }) { + return ( +
e.stopPropagation()}> + +
+ ); + }, + cell({ row }) { + return ( +
e.stopPropagation()}> + +
+ ); + } + }), + columnHelper.accessor((row) => row.fileName, { + header({ column }) { + return ( + + {t('fileName')} + + ); + }, + id: TableHeaderID.fileName, + enablePinning: true, + sortDescFirst: true, + cell(props) { + const file = props.row.original; + return ( + + {file.isDir ? ( + + ) : ( + + )} + + + {file.fileName} + + + + ); + }, + sortingFn: 'textCaseSensitive' + }), + columnHelper.accessor((row) => row.Size, { + header({ column }) { + return ( + + {t('fileSize')} + + ); + }, + id: TableHeaderID.fileSize, + enablePinning: true, + cell(props) { + const file = props.row.original; + return ( + + {file.isDir ? '--' : formatBytes(file.Size || 0).toString()} + + ); + }, + sortingFn(row1, row2, id) { + const size1 = row1.getValue(id); + const size2 = row2.getValue(id); + if (size2 === void 0) { + return 1; + } else if (size1 === void 0) { + return -1; + } else { + return size1 > size2 ? 1 : size2 > size1 ? -1 : 0; + } + } + }), + columnHelper.accessor((row) => row.type, { + header({ column }) { + return ( + + {t('fileType')} + + ); + }, + cell({ cell }) { + return {cell.getValue()}; + }, + id: TableHeaderID.fileType, + enablePinning: true, + sortingFn: 'text' + }), + columnHelper.accessor((row) => row.LastModified, { + header(props) { + return ( + + {t('modifiedTime')} + + ); + }, + id: TableHeaderID.modifiedTime, + cell(props) { + const dateVal = props.cell.getValue(); + return ( + + {dateVal ? format(dateVal, 'yyyy/MM/dd hh:mm') : ''} + + ); + }, + sortingFn: 'datetime' + }), + columnHelper.display({ + header() { + return t('action'); + }, + id: TableHeaderID.action, + enablePinning: true, + cell(props) { + const file = props.row.original; + return ( + + {!file.isDir && ( + } + p="5px" + onClick={(e) => { + e.stopPropagation(); + if (!s3client || !Bucket) return; + generateUrl(s3client, Bucket, file.Key) + .then((url) => { + window.open(new URL(url)); + }) + .catch(() => { + toast({ + status: 'error', + title: 'get url error' + }); + }); + }} + aria-label={'preview'} + /> + )} + {!file.isDir && ( + } + p="5px" + onClick={(e) => { + e.stopPropagation(); + if (!s3client || !Bucket) return; + generateUrl(s3client, Bucket, file.Key) + .then((url) => { + copyData(url); + }) + .catch((err) => { + toast({ + status: 'error', + title: 'get url error' + }); + }); + }} + aria-label={'link'} + /> + )} + {!(file.isDir && file.type === 'link') && ( + { + deleteEntry(file); + }} + /> + )} + + ); + } + }) + ]; + }, [t, Bucket, s3client]); + const table = useReactTable({ + data: fileList, + state: { + columnPinning: { + left: [TableHeaderID.select, TableHeaderID.fileName], + right: [TableHeaderID.action] + } + }, + enableRowSelection(row) { + const file = row.original; + return !(file.type === 'link' && file.isDir); + }, + enableSorting: true, + enableColumnPinning: true, + columns, + getSortedRowModel: getSortedRowModel(), + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + debugTable: false + }); return ( @@ -282,8 +579,10 @@ export default function FileManager({ ...styles }: FlexProps) { type="text" maxW="270px" placeholder={t('searchFile')} - onChange={(v) => setSearchVal(v.target.value.trim())} - value={searchVal} + onChange={(v) => + table.getColumn(TableHeaderID.fileName)?.setFilterValue(v.target.value.trim()) + } + value={table.getColumn(TableHeaderID.fileName)?.getFilterValue() as string} /> { - multiDeleteEntry(deleteCheckBoxGroupState.value as string[]); + multiDeleteEntry(table.getSelectedRowModel().rows.map((v) => v.original.Key)); }} - fileListLength={deleteCheckBoxGroupState.value.length} + fileListLength={table.getSelectedRowModel().rows.length} />