From 79b0cae57275d2965e7517e11e9a029bef84c250 Mon Sep 17 00:00:00 2001 From: jingyang <72259332+zjy365@users.noreply.github.com> Date: Fri, 13 Sep 2024 11:00:36 +0800 Subject: [PATCH] feat(applaunchpad): Improve domain handling for legacy and new domains (#5011) * update docs * feat:domain * update * update default * delete log * update default user domain * delete get env * fix custom * delete log --- docs/website/src/hooks/useWindow.ts | 3 +- .../src/pages/components/Header/index.tsx | 4 +- docs/website/src/pages/index.tsx | 3 + docs/website/src/pages/self-hosting/index.tsx | 3 + .../public/locales/en/common.json | 5 +- .../public/locales/zh/common.json | 3 +- .../applaunchpad/src/api/platform.ts | 3 - .../applaunchpad/src/constants/editApp.ts | 4 +- .../providers/applaunchpad/src/mock/apps.ts | 3 +- .../src/pages/api/platform/getEnv.ts | 13 --- .../src/pages/api/platform/getInitData.ts | 8 +- .../app/detail/components/AppMainInfo.tsx | 4 +- .../app/edit/components/CustomAccessModal.tsx | 16 ++- .../src/pages/app/edit/components/Form.tsx | 13 ++- .../applaunchpad/src/store/static.ts | 2 + .../providers/applaunchpad/src/types/app.d.ts | 3 +- .../applaunchpad/src/types/index.d.ts | 1 + .../providers/applaunchpad/src/utils/adapt.ts | 107 ++---------------- .../applaunchpad/src/utils/deployYaml2Json.ts | 4 +- 19 files changed, 67 insertions(+), 135 deletions(-) delete mode 100644 frontend/providers/applaunchpad/src/pages/api/platform/getEnv.ts diff --git a/docs/website/src/hooks/useWindow.ts b/docs/website/src/hooks/useWindow.ts index 45cba0d185f..9a1a6aa628c 100644 --- a/docs/website/src/hooks/useWindow.ts +++ b/docs/website/src/hooks/useWindow.ts @@ -4,6 +4,7 @@ import useIsBrowser from '@docusaurus/useIsBrowser'; interface SemParams { bd_vid: string; keywords: string; + s: string; } export default function useWindow() { @@ -13,7 +14,7 @@ export default function useWindow() { isBrowser ? document.documentElement.lang : 'en' ); const [cloudUrl, setCloudUrl] = useState('https://cloud.sealos.io'); - const [semParams, setSemParams] = useState({ bd_vid: '', keywords: '' }); + const [semParams, setSemParams] = useState({ bd_vid: '', keywords: '', s: '' }); useEffect(() => { if (!isBrowser) return; diff --git a/docs/website/src/pages/components/Header/index.tsx b/docs/website/src/pages/components/Header/index.tsx index 22d5fda046f..d11a8eefc8f 100644 --- a/docs/website/src/pages/components/Header/index.tsx +++ b/docs/website/src/pages/components/Header/index.tsx @@ -142,7 +142,7 @@ const HomeHeader = ({ isPc }: { isPc: boolean }) => { )} {i18nObj.startNow} @@ -201,7 +201,7 @@ const HomeHeader = ({ isPc }: { isPc: boolean }) => { )} {i18nObj.startNow} diff --git a/docs/website/src/pages/index.tsx b/docs/website/src/pages/index.tsx index 8e5de39ea4f..7e5c5ebef25 100644 --- a/docs/website/src/pages/index.tsx +++ b/docs/website/src/pages/index.tsx @@ -50,6 +50,9 @@ const Home = () => { const k = urlParams.get('k'); if (k) params.keywords = k; + const s = urlParams.get('s'); + if (s) params.s = s; + if (Object.keys(params).length > 0) { sessionStorage.setItem('sealos_sem', JSON.stringify(params)); } diff --git a/docs/website/src/pages/self-hosting/index.tsx b/docs/website/src/pages/self-hosting/index.tsx index 15e316a725b..80b9be8f4c0 100644 --- a/docs/website/src/pages/self-hosting/index.tsx +++ b/docs/website/src/pages/self-hosting/index.tsx @@ -27,6 +27,9 @@ export default function Pricing() { const k = urlParams.get('k'); if (k) params.keywords = k; + const s = urlParams.get('s'); + if (s) params.s = s; + if (Object.keys(params).length > 0) { sessionStorage.setItem('sealos_sem', JSON.stringify(params)); } diff --git a/frontend/providers/applaunchpad/public/locales/en/common.json b/frontend/providers/applaunchpad/public/locales/en/common.json index a9437fd7847..d7868afe211 100644 --- a/frontend/providers/applaunchpad/public/locales/en/common.json +++ b/frontend/providers/applaunchpad/public/locales/en/common.json @@ -265,5 +265,6 @@ "within_1_hour": "Within 1 hour", "within_1_day": "Within 1 day", "terminated_logs": "Terminated logs", - "no_logs_for_now": "No logs for now" -} + "no_logs_for_now": "No logs for now", + "or": "or" +} \ No newline at end of file diff --git a/frontend/providers/applaunchpad/public/locales/zh/common.json b/frontend/providers/applaunchpad/public/locales/zh/common.json index fb66cdb3e56..8fb7cb20a65 100644 --- a/frontend/providers/applaunchpad/public/locales/zh/common.json +++ b/frontend/providers/applaunchpad/public/locales/zh/common.json @@ -265,5 +265,6 @@ "within_1_hour": "一小时内", "within_1_day": "一天内", "terminated_logs": "中断前", - "no_logs_for_now": "暂无日志" + "no_logs_for_now": "暂无日志", + "or": "或" } \ No newline at end of file diff --git a/frontend/providers/applaunchpad/src/api/platform.ts b/frontend/providers/applaunchpad/src/api/platform.ts index 98f0b42dd72..a4817dd2858 100644 --- a/frontend/providers/applaunchpad/src/api/platform.ts +++ b/frontend/providers/applaunchpad/src/api/platform.ts @@ -16,9 +16,6 @@ export const getUserQuota = () => export const postAuthCname = (data: AuthCnamePrams) => POST('/api/platform/authCname', data); -// abandoned -export const getPlatformEnv = () => GET('/api/platform/getEnv'); - export const updateDesktopGuide = (payload: UpdateUserGuideParams) => POST('/api/guide/updateGuide', payload); diff --git a/frontend/providers/applaunchpad/src/constants/editApp.ts b/frontend/providers/applaunchpad/src/constants/editApp.ts index 48801cbfbfa..c0ef9fa66bb 100644 --- a/frontend/providers/applaunchpad/src/constants/editApp.ts +++ b/frontend/providers/applaunchpad/src/constants/editApp.ts @@ -1,3 +1,4 @@ +import { SEALOS_DOMAIN, SEALOS_USER_DOMAIN } from '@/store/static'; import type { AppEditType } from '@/types/app'; import { customAlphabet } from 'nanoid'; const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 12); @@ -38,7 +39,8 @@ export const defaultEditVal: AppEditType = { protocol: 'HTTP', openPublicDomain: false, publicDomain: '', - customDomain: '' + customDomain: '', + domain: '' } ], envs: [], diff --git a/frontend/providers/applaunchpad/src/mock/apps.ts b/frontend/providers/applaunchpad/src/mock/apps.ts index ae0b03fe78e..34d9e06e7de 100644 --- a/frontend/providers/applaunchpad/src/mock/apps.ts +++ b/frontend/providers/applaunchpad/src/mock/apps.ts @@ -268,7 +268,8 @@ export const MOCK_APP_DETAIL: AppDetailType = { protocol: 'HTTP', openPublicDomain: false, publicDomain: '', - customDomain: '' + customDomain: '', + domain: '' } ], envs: [], diff --git a/frontend/providers/applaunchpad/src/pages/api/platform/getEnv.ts b/frontend/providers/applaunchpad/src/pages/api/platform/getEnv.ts deleted file mode 100644 index 27fd3c720a2..00000000000 --- a/frontend/providers/applaunchpad/src/pages/api/platform/getEnv.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { jsonRes } from '@/services/backend/response'; -import { ApiResp } from '@/services/kubernet'; -import { EnvResponse } from '@/types/index'; -import type { NextApiRequest, NextApiResponse } from 'next'; - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - jsonRes(res, { - data: { - domain: global.AppConfig.cloud.domain || 'cloud.sealos.io', - guideEnabled: global.AppConfig.common.guideEnabled - } - }); -} diff --git a/frontend/providers/applaunchpad/src/pages/api/platform/getInitData.ts b/frontend/providers/applaunchpad/src/pages/api/platform/getInitData.ts index ecacaac51f7..20b4df5fdde 100644 --- a/frontend/providers/applaunchpad/src/pages/api/platform/getInitData.ts +++ b/frontend/providers/applaunchpad/src/pages/api/platform/getInitData.ts @@ -16,12 +16,14 @@ export type Response = { CURRENCY: Coin; guideEnabled: boolean; fileMangerConfig: FileMangerType; + SEALOS_USER_DOMAIN: string[]; }; export const defaultAppConfig: AppConfigType = { cloud: { domain: 'cloud.sealos.io', - port: '' + port: '', + userDomain: ['cloud.sealos.io'] }, common: { guideEnabled: false, @@ -74,6 +76,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const gpuNodes = await getGpuNode(); global.AppConfig.common.gpuEnabled = gpuNodes.length > 0; } + jsonRes(res, { data: { SEALOS_DOMAIN: global.AppConfig.cloud.domain, @@ -83,7 +86,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) FORM_SLIDER_LIST_CONFIG: global.AppConfig.launchpad.appResourceFormSliderConfig, guideEnabled: global.AppConfig.common.guideEnabled, fileMangerConfig: global.AppConfig.launchpad.fileManger, - CURRENCY: Coin.shellCoin + CURRENCY: Coin.shellCoin, + SEALOS_USER_DOMAIN: global.AppConfig.cloud.userDomain || [] } }); } catch (error) { diff --git a/frontend/providers/applaunchpad/src/pages/app/detail/components/AppMainInfo.tsx b/frontend/providers/applaunchpad/src/pages/app/detail/components/AppMainInfo.tsx index 1fa4ef20182..7b050b6afea 100644 --- a/frontend/providers/applaunchpad/src/pages/app/detail/components/AppMainInfo.tsx +++ b/frontend/providers/applaunchpad/src/pages/app/detail/components/AppMainInfo.tsx @@ -4,7 +4,7 @@ import { MyTooltip } from '@sealos/ui'; import PodLineChart from '@/components/PodLineChart'; import { ProtocolList } from '@/constants/app'; import { MOCK_APP_DETAIL } from '@/mock/apps'; -import { DOMAIN_PORT, SEALOS_DOMAIN } from '@/store/static'; +import { DOMAIN_PORT } from '@/store/static'; import type { AppDetailType } from '@/types/app'; import { useCopyData } from '@/utils/tools'; import { getUserNamespace } from '@/utils/user'; @@ -27,7 +27,7 @@ const AppMainInfo = ({ app = MOCK_APP_DETAIL }: { app: AppDetailType }) => { ? `${ProtocolList.find((item) => item.value === network.protocol)?.label}${ network.customDomain ? network.customDomain - : `${network.publicDomain}.${SEALOS_DOMAIN}${DOMAIN_PORT}` + : `${network.publicDomain}.${network.domain}${DOMAIN_PORT}` }` : '' })), diff --git a/frontend/providers/applaunchpad/src/pages/app/edit/components/CustomAccessModal.tsx b/frontend/providers/applaunchpad/src/pages/app/edit/components/CustomAccessModal.tsx index 98886794efb..66ff4e18c4d 100644 --- a/frontend/providers/applaunchpad/src/pages/app/edit/components/CustomAccessModal.tsx +++ b/frontend/providers/applaunchpad/src/pages/app/edit/components/CustomAccessModal.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useMemo, useRef } from 'react'; +import React, { useMemo, useRef } from 'react'; import { Box, ModalBody, @@ -15,20 +15,22 @@ import { ModalHeader } from '@chakra-ui/react'; import { useTranslation } from 'react-i18next'; -import { SEALOS_DOMAIN } from '@/store/static'; import { Tip } from '@sealos/ui'; import { InfoOutlineIcon } from '@chakra-ui/icons'; import { useRequest } from '@/hooks/useRequest'; import { postAuthCname } from '@/api/platform'; +import { SEALOS_USER_DOMAIN } from '@/store/static'; export type CustomAccessModalParams = { publicDomain: string; customDomain: string; + domain: string; }; const CustomAccessModal = ({ publicDomain, customDomain, + domain, onClose, onSuccess }: CustomAccessModalParams & { onClose: () => void; onSuccess: (e: string) => void }) => { @@ -41,7 +43,11 @@ const CustomAccessModal = ({ mb: 2 }; - const completePublicDomain = useMemo(() => `${publicDomain}.${SEALOS_DOMAIN}`, [publicDomain]); + const completePublicDomain = useMemo(() => `${publicDomain}.${domain}`, [publicDomain, domain]); + + const cnameTips = useMemo(() => { + return SEALOS_USER_DOMAIN.map((item) => `${publicDomain}.${item}`).join(` ${t('or')} `); + }, [publicDomain, t]); const { mutate: authCNAME, isLoading } = useRequest({ mutationFn: async () => { @@ -95,7 +101,9 @@ const CustomAccessModal = ({ size={'sm'} whiteSpace={'pre-wrap'} icon={} - text={`${t('CNAME Tips', { domain: completePublicDomain })}`} + text={`${t('CNAME Tips', { + domain: customDomain ? cnameTips : completePublicDomain + })}`} /> 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 23789e560aa..030e75b25a9 100644 --- a/frontend/providers/applaunchpad/src/pages/app/edit/components/Form.tsx +++ b/frontend/providers/applaunchpad/src/pages/app/edit/components/Form.tsx @@ -5,7 +5,7 @@ import { defaultSliderKey, ProtocolList } from '@/constants/app'; import { GpuAmountMarkList } from '@/constants/editApp'; import { useToast } from '@/hooks/useToast'; import { useGlobalStore } from '@/store/global'; -import { SEALOS_DOMAIN } from '@/store/static'; +import { SEALOS_DOMAIN, SEALOS_USER_DOMAIN } from '@/store/static'; import { useUserStore } from '@/store/user'; import type { QueryType } from '@/types'; import type { AppEditType } from '@/types/app'; @@ -802,7 +802,8 @@ const Form = ({ protocol: 'HTTP', openPublicDomain: false, publicDomain: '', - customDomain: '' + customDomain: '', + domain: SEALOS_DOMAIN }) } > @@ -826,7 +827,8 @@ const Form = ({ networkName: network.networkName || `network-${nanoid()}`, protocol: network.protocol || 'HTTP', openPublicDomain: e.target.checked, - publicDomain: network.publicDomain || nanoid() + publicDomain: network.publicDomain || nanoid(), + domain: network.domain || SEALOS_DOMAIN }); }} /> @@ -867,7 +869,7 @@ const Form = ({ {network.customDomain ? network.customDomain - : `${network.publicDomain}.${SEALOS_DOMAIN}`} + : `${network.publicDomain}.${network.domain}`} setCustomAccessModalData({ publicDomain: network.publicDomain, - customDomain: network.customDomain + customDomain: network.customDomain, + domain: network.domain }) } > diff --git a/frontend/providers/applaunchpad/src/store/static.ts b/frontend/providers/applaunchpad/src/store/static.ts index 185e66600af..e0c3f8bba1c 100644 --- a/frontend/providers/applaunchpad/src/store/static.ts +++ b/frontend/providers/applaunchpad/src/store/static.ts @@ -2,6 +2,7 @@ import { getInitData } from '@/api/platform'; import { Coin } from '@/constants/app'; export let SEALOS_DOMAIN = 'cloud.sealos.io'; +export let SEALOS_USER_DOMAIN = ['cloud.sealos.io']; export let DOMAIN_PORT = ''; export let INGRESS_SECRET = 'wildcard-cert'; export let SHOW_EVENT_ANALYZE = false; @@ -13,6 +14,7 @@ export const loadInitData = async () => { try { const res = await getInitData(); SEALOS_DOMAIN = res.SEALOS_DOMAIN; + SEALOS_USER_DOMAIN = res.SEALOS_USER_DOMAIN; DOMAIN_PORT = res.DOMAIN_PORT; INGRESS_SECRET = res.INGRESS_SECRET; SHOW_EVENT_ANALYZE = res.SHOW_EVENT_ANALYZE; diff --git a/frontend/providers/applaunchpad/src/types/app.d.ts b/frontend/providers/applaunchpad/src/types/app.d.ts index b8889331587..5b1cca0a953 100644 --- a/frontend/providers/applaunchpad/src/types/app.d.ts +++ b/frontend/providers/applaunchpad/src/types/app.d.ts @@ -76,8 +76,9 @@ export interface AppEditType { port: number; protocol: ProtocolType; openPublicDomain: boolean; - publicDomain: string; // default domain + publicDomain: string; // default domain // domainPrefix customDomain: string; // custom domain + domain: string; }[]; envs: { key: string; diff --git a/frontend/providers/applaunchpad/src/types/index.d.ts b/frontend/providers/applaunchpad/src/types/index.d.ts index e886c2fdb40..49e73a8b0c2 100644 --- a/frontend/providers/applaunchpad/src/types/index.d.ts +++ b/frontend/providers/applaunchpad/src/types/index.d.ts @@ -27,6 +27,7 @@ export type AppConfigType = { cloud: { domain: string; port?: string; + userDomain: string[]; }; common: { guideEnabled: boolean; diff --git a/frontend/providers/applaunchpad/src/utils/adapt.ts b/frontend/providers/applaunchpad/src/utils/adapt.ts index bff96e334a9..c63fcc077de 100644 --- a/frontend/providers/applaunchpad/src/utils/adapt.ts +++ b/frontend/providers/applaunchpad/src/utils/adapt.ts @@ -219,7 +219,7 @@ export enum YamlKindEnum { } export const adaptAppDetail = async (configs: DeployKindsType[]): Promise => { - const { SEALOS_DOMAIN } = await getInitData(); + const { SEALOS_DOMAIN, SEALOS_USER_DOMAIN } = await getInitData(); const deployKindsMap: { [YamlKindEnum.StatefulSet]?: V1StatefulSet; [YamlKindEnum.Deployment]?: V1Deployment; @@ -312,21 +312,23 @@ export const adaptAppDetail = async (configs: DeployKindsType[]): Promise domain.endsWith(user)); + return { networkName: ingress?.metadata?.name || '', portName: item.name || '', port: item.port, protocol: protocol, openPublicDomain: !!ingress, - ...(domain.endsWith(SEALOS_DOMAIN) - ? { - publicDomain: domain.split('.')[0], - customDomain: '' - } - : { - publicDomain: ingress?.metadata?.labels?.[publicDomainKey] || '', - customDomain: domain - }) + publicDomain: isCustomDomain + ? ingress?.metadata?.labels?.[publicDomainKey] || '' + : domain.split('.')[0], + customDomain: isCustomDomain ? domain : '', + domain: isCustomDomain + ? SEALOS_DOMAIN + : domain.split('.').slice(1).join('.') || SEALOS_DOMAIN }; }) || [], hpa: deployKindsMap.HorizontalPodAutoscaler?.spec @@ -390,91 +392,6 @@ export const adaptEditAppData = (app: AppDetailType): AppEditType => { return res as AppEditType; }; -// yaml file adapt to edit form -export const adaptYamlToEdit = (yamlList: string[]) => { - const configs = yamlList.map((item) => yaml.loadAll(item) as DeployKindsType).flat(); - - const deployKindsMap: { - [YamlKindEnum.Deployment]?: V1Deployment; - [YamlKindEnum.Service]?: V1Service; - [YamlKindEnum.ConfigMap]?: V1ConfigMap; - [YamlKindEnum.Ingress]?: V1Ingress; - [YamlKindEnum.HorizontalPodAutoscaler]?: V2HorizontalPodAutoscaler; - [YamlKindEnum.Secret]?: V1Secret; - } = {}; - - configs.forEach((item) => { - if (item.kind) { - // @ts-ignore - deployKindsMap[item.kind] = item; - } - }); - - const domain = deployKindsMap?.Ingress?.spec?.rules?.[0].host; - const cpuStr = - deployKindsMap?.Deployment?.spec?.template?.spec?.containers?.[0]?.resources?.requests?.cpu; - const memoryStr = - deployKindsMap?.Deployment?.spec?.template?.spec?.containers?.[0]?.resources?.requests?.memory; - - const res: Record = { - imageName: deployKindsMap?.Deployment?.spec?.template?.spec?.containers?.[0]?.image, - runCMD: - deployKindsMap?.Deployment?.spec?.template?.spec?.containers?.[0]?.command?.join(' ') || '', - cmdParam: - deployKindsMap?.Deployment?.spec?.template?.spec?.containers?.[0]?.args?.join(' ') || '', - replicas: deployKindsMap?.Deployment?.spec?.replicas, - cpu: cpuStr ? cpuFormatToM(cpuStr) : undefined, - memory: memoryStr ? memoryFormatToMi(memoryStr) : undefined, - accessExternal: deployKindsMap?.Ingress - ? { - use: true, - outDomain: domain?.split('.')[0], - selfDomain: domain - } - : undefined, - containerOutPort: - deployKindsMap?.Deployment?.spec?.template?.spec?.containers?.[0]?.ports?.[0]?.containerPort, - envs: - deployKindsMap?.Deployment?.spec?.template?.spec?.containers?.[0]?.env?.map((env) => ({ - key: env.name, - value: env.value - })) || undefined, - hpa: deployKindsMap.HorizontalPodAutoscaler?.spec - ? { - use: true, - target: - (deployKindsMap.HorizontalPodAutoscaler.spec.metrics?.[0]?.resource - ?.name as HpaTarget) || 'cpu', - value: - deployKindsMap.HorizontalPodAutoscaler.spec.metrics?.[0]?.resource?.target - ?.averageUtilization || 50, - minReplicas: deployKindsMap.HorizontalPodAutoscaler.spec?.maxReplicas, - maxReplicas: deployKindsMap.HorizontalPodAutoscaler.spec?.minReplicas - } - : undefined, - configMapList: deployKindsMap?.ConfigMap?.data - ? Object.entries(deployKindsMap?.ConfigMap.data).map(([key, value]) => ({ - mountPath: key, - value - })) - : undefined, - secret: deployKindsMap.Secret - ? { - ...defaultEditVal.secret, - use: true - } - : undefined - }; - - for (const key in res) { - if (res[key] === undefined) { - delete res[key]; - } - } - - return res; -}; - export const sliderNumber2MarkList = ({ val, type, diff --git a/frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts b/frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts index d477717d8d2..1dcd33e1eda 100644 --- a/frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts +++ b/frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts @@ -7,7 +7,7 @@ import { minReplicasKey, publicDomainKey } from '@/constants/app'; -import { INGRESS_SECRET, SEALOS_DOMAIN } from '@/store/static'; +import { INGRESS_SECRET } from '@/store/static'; import type { AppEditType } from '@/types/app'; import { pathFormat, pathToNameFormat, str2Num, strToBase64 } from '@/utils/tools'; import dayjs from 'dayjs'; @@ -272,7 +272,7 @@ export const json2Ingress = (data: AppEditType) => { .map((network, i) => { const host = network.customDomain ? network.customDomain - : `${network.publicDomain}.${SEALOS_DOMAIN}`; + : `${network.publicDomain}.${network.domain}`; const secretName = network.customDomain ? network.networkName : INGRESS_SECRET;