mirror of
https://github.com/labring/sealos.git
synced 2026-09-24 15:46:19 +08:00
feat: add region switch proxy (#5532)
* fix: launchpad tcp value & switch region update swithch region update add cf worker update update update .lintstagedrc * delete log * update * update name * update launchpad * update page
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,12 @@ import { useRouter } from 'next/router';
|
||||
import { useMemo } from 'react';
|
||||
import { DesktopExchangeIcon, ZoneIcon } from '../icons';
|
||||
import { I18nCloudProvidersKey } from '@/types/i18next';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
|
||||
export default function RegionToggle() {
|
||||
const disclosure = useDisclosure();
|
||||
const { setWorkSpaceId, session } = useSessionStore();
|
||||
const { cloudConfig } = useConfigStore();
|
||||
const { t, i18n } = useTranslation();
|
||||
const router = useRouter();
|
||||
const { data } = useQuery(['regionlist'], getRegionList, {
|
||||
@@ -36,11 +38,17 @@ export default function RegionToggle() {
|
||||
|
||||
const handleCick = async (region: Region) => {
|
||||
setWorkSpaceId(session?.user?.ns_uid || '');
|
||||
const target = new URL(`https://${region.domain}/switchRegion`);
|
||||
const target = new URL(
|
||||
cloudConfig?.proxyDomain
|
||||
? `https://${cloudConfig?.proxyDomain}/switchRegion`
|
||||
: `https://${region.domain}/switchRegion`
|
||||
);
|
||||
const res = await request.get<any, ApiResp<{ token: string }>>('/api/auth/globalToken');
|
||||
const token = res?.data?.token;
|
||||
if (!token) return;
|
||||
target.searchParams.append('token', token);
|
||||
target.searchParams.append('regionId', region.uid);
|
||||
target.searchParams.append('regionDomain', region.domain);
|
||||
await router.replace(target);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
function genResCloudConfig(conf: CloudConfigType): CloudConfigType {
|
||||
return {
|
||||
domain: conf.domain,
|
||||
port: conf.port
|
||||
port: conf.port,
|
||||
proxyDomain: conf.proxyDomain
|
||||
} as CloudConfigType;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ export type CloudConfigType = {
|
||||
port: string;
|
||||
regionUID: string;
|
||||
certSecretName: string;
|
||||
proxyDomain: string;
|
||||
};
|
||||
|
||||
export type CommonConfigType = {
|
||||
@@ -254,7 +255,8 @@ export const DefaultCloudConfig: CloudConfigType = {
|
||||
domain: 'cloud.sealos.io',
|
||||
port: '443',
|
||||
regionUID: 'sealos-cloud',
|
||||
certSecretName: 'wildcard-cert'
|
||||
certSecretName: 'wildcard-cert',
|
||||
proxyDomain: 'cloud.sealos.io'
|
||||
};
|
||||
|
||||
export const DefaultLayoutConfig: LayoutConfigType = {
|
||||
|
||||
@@ -45,7 +45,7 @@ const AppMainInfo = ({ app = MOCK_APP_DETAIL }: { app: AppDetailType }) => {
|
||||
inline: `${protocol?.inline}${app.appName}.${getUserNamespace()}.svc.cluster.local:${
|
||||
network.port
|
||||
}`,
|
||||
public: `${protocol?.label}${network.domain}${
|
||||
public: `${protocol?.label}${protocol?.value.toLowerCase()}.${network.domain}${
|
||||
network?.nodePort ? `:${network.nodePort}` : ''
|
||||
}`,
|
||||
showReadyStatus: false
|
||||
|
||||
@@ -97,6 +97,7 @@ const Form = ({
|
||||
control,
|
||||
name: 'networks'
|
||||
});
|
||||
|
||||
const { fields: envs, replace: replaceEnvs } = useFieldArray({
|
||||
control,
|
||||
name: 'envs'
|
||||
@@ -970,8 +971,12 @@ const Form = ({
|
||||
? network.customDomain
|
||||
: network.openNodePort
|
||||
? network?.nodePort
|
||||
? `${network.domain}:${network.nodePort}`
|
||||
: `${network.domain}:${t('pending_to_allocated')}`
|
||||
? `${network.protocol.toLowerCase()}.${network.domain}:${
|
||||
network.nodePort
|
||||
}`
|
||||
: `${network.protocol.toLowerCase()}.${network.domain}:${t(
|
||||
'pending_to_allocated'
|
||||
)}`
|
||||
: `${network.publicDomain}.${network.domain}`}
|
||||
</Box>
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY ./index.html /usr/share/nginx/html/index.html
|
||||
COPY ./nginx.conf /etc/nginx/nginx.conf
|
||||
@@ -0,0 +1,87 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: desktop-switch-region
|
||||
namespace: sealos
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: desktop-switch-region
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 0
|
||||
maxSurge: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: desktop-switch-region
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- name: desktop-switch-region
|
||||
image: ghcr.io/labring/sealos-desktop-switch-region:latest
|
||||
env: []
|
||||
resources:
|
||||
requests:
|
||||
cpu: 20m
|
||||
memory: 25Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: pwihfnbsxdbv
|
||||
imagePullPolicy: Always
|
||||
volumeMounts: []
|
||||
volumes: []
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: desktop-switch-region
|
||||
namespace: sealos
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
name: pwihfnbsxdbv
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: desktop-switch-region
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: desktop-switch-region
|
||||
namespace: sealos
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: nginx
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: 32m
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: 'false'
|
||||
nginx.ingress.kubernetes.io/backend-protocol: HTTP
|
||||
nginx.ingress.kubernetes.io/client-body-buffer-size: 64k
|
||||
nginx.ingress.kubernetes.io/proxy-buffer-size: 64k
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: '300'
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: '300'
|
||||
nginx.ingress.kubernetes.io/server-snippet: |
|
||||
client_header_buffer_size 64k;
|
||||
large_client_header_buffers 4 128k;
|
||||
spec:
|
||||
rules:
|
||||
- host: cloud.sealos.run
|
||||
http:
|
||||
paths:
|
||||
- pathType: Prefix
|
||||
path: /
|
||||
backend:
|
||||
service:
|
||||
name: desktop-switch-region
|
||||
port:
|
||||
number: 80
|
||||
tls:
|
||||
- hosts:
|
||||
- cloud.sealos.run
|
||||
secretName: wildcard-cert
|
||||
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Region Switching</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
(function () {
|
||||
const DEFAULT_REGION = 'hzh.sealos.run'
|
||||
|
||||
const REGION_MAP = {
|
||||
xxx: 'xxx'
|
||||
}
|
||||
|
||||
function getUrlParam (name) {
|
||||
const url = new URL(window.location.href)
|
||||
return url.searchParams.get(name)
|
||||
}
|
||||
|
||||
function setLocalStorage (name, value) {
|
||||
localStorage.setItem(name, value)
|
||||
}
|
||||
|
||||
function getLocalStorage (name) {
|
||||
return localStorage.getItem(name)
|
||||
}
|
||||
|
||||
function validateRegion (regionId, regionDomain) {
|
||||
if (!regionId || !regionDomain) return false
|
||||
return REGION_MAP[regionId] === regionDomain
|
||||
}
|
||||
|
||||
function buildTargetUrl (targetRegion, pathname, url) {
|
||||
let targetUrl = `https://${targetRegion}${pathname}`
|
||||
|
||||
const params = url.search
|
||||
if (params) {
|
||||
targetUrl += params
|
||||
}
|
||||
|
||||
return targetUrl
|
||||
}
|
||||
|
||||
function redirect () {
|
||||
const url = new URL(window.location.href)
|
||||
const regionId = getUrlParam('regionId')
|
||||
const regionDomain = getUrlParam('regionDomain')
|
||||
|
||||
const isValid = validateRegion(regionId, regionDomain)
|
||||
|
||||
if (isValid) {
|
||||
setLocalStorage('latest_region', regionDomain)
|
||||
setLocalStorage('latest_region_id', regionId)
|
||||
|
||||
const targetRegion = regionDomain
|
||||
const targetUrl = buildTargetUrl(targetRegion, url.pathname, url)
|
||||
|
||||
window.location.href = targetUrl
|
||||
} else {
|
||||
const savedRegionId = getLocalStorage('latest_region_id')
|
||||
const savedRegion = getLocalStorage('latest_region')
|
||||
|
||||
const isSavedValid = savedRegionId && savedRegion && REGION_MAP[savedRegionId] === savedRegion
|
||||
|
||||
const targetRegion = isSavedValid ? savedRegion : DEFAULT_REGION
|
||||
const targetUrl = buildTargetUrl(targetRegion, url.pathname, url)
|
||||
|
||||
window.location.href = targetUrl
|
||||
}
|
||||
}
|
||||
|
||||
redirect()
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,49 @@
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires max;
|
||||
add_header Cache-Control "public, max-age=31536000";
|
||||
log_not_found off;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ function Terminal({ url, site }: { url: string; site: string }) {
|
||||
);
|
||||
iframeRef.current?.contentWindow?.postMessage(
|
||||
{
|
||||
command: `echo -e "\\e[A\\e[K 👉 Switched to namespace \\e[1;4;32m${nsid}\\e[0m" && history -c`
|
||||
command: `echo -e "This is a temporary terminal for debugging and testing. The session will automatically end 30 minutes after you leave.\\n\\nYou are now working in: namespace ${nsid}" && history -c`
|
||||
},
|
||||
url
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user