feat: 增加节点切换
Some checks failed
sync2gitee / repo-sync (push) Failing after -7m11s

This commit is contained in:
ssongliu 2024-07-29 14:13:47 +08:00
parent d6c5cab08d
commit 865b6cba3f
11 changed files with 131 additions and 34 deletions

View file

@ -40,6 +40,10 @@ build_agent_on_darwin:
cd $(AGENT_PATH) \ cd $(AGENT_PATH) \
&& GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN) && GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
build_agent_xpack_on_darwin:
cd $(AGENT_PATH) \
&& GOOS=linux GOARCH=amd64 $(GOBUILD) -tags=xpack -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
build_all: build_frontend build_core_on_linux build_agent_on_linux build_all: build_frontend build_core_on_linux build_agent_on_linux
build_on_local: clean_assets build_frontend build_core_on_darwin build_agent_on_darwin upx_bin build_on_local: clean_assets build_frontend build_core_on_darwin build_agent_on_darwin upx_bin

View file

@ -1,5 +1,5 @@
system: system:
db_file: agent.db db_agent_file: agent.db
base_dir: /opt base_dir: /opt
mode: dev mode: dev
repo_url: https://resource.fit2cloud.com/1panel/package repo_url: https://resource.fit2cloud.com/1panel/package

View file

@ -26,5 +26,7 @@ var (
MonitorCronID cron.EntryID MonitorCronID cron.EntryID
OneDriveCronID cron.EntryID OneDriveCronID cron.EntryID
CurrentNode string
I18n *i18n.Localizer I18n *i18n.Localizer
) )

View file

@ -2,7 +2,6 @@ package router
import ( import (
"github.com/1Panel-dev/1Panel/agent/i18n" "github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/middleware"
rou "github.com/1Panel-dev/1Panel/agent/router" rou "github.com/1Panel-dev/1Panel/agent/router"
"github.com/gin-contrib/gzip" "github.com/gin-contrib/gzip"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -12,13 +11,6 @@ var (
Router *gin.Engine Router *gin.Engine
) )
func setWebStatic(rootRouter *gin.RouterGroup) {
rootRouter.Static("/api/v1/images", "./uploads")
rootRouter.Use(func(c *gin.Context) {
c.Next()
})
}
func Routers() *gin.Engine { func Routers() *gin.Engine {
Router = gin.Default() Router = gin.Default()
Router.Use(i18n.UseI18n()) Router.Use(i18n.UseI18n())
@ -29,10 +21,9 @@ func Routers() *gin.Engine {
c.JSON(200, "ok") c.JSON(200, "ok")
}) })
PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression)) PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression))
setWebStatic(PublicGroup) PublicGroup.Static("/api/v1/images", "./uploads")
} }
PrivateGroup := Router.Group("/api/v2") PrivateGroup := Router.Group("/api/v2")
PrivateGroup.Use(middleware.GlobalLoading())
for _, router := range rou.RouterGroupApp { for _, router := range rou.RouterGroupApp {
router.InitRouter(PrivateGroup) router.InitRouter(PrivateGroup)
} }

View file

@ -6,6 +6,7 @@ import (
"os" "os"
"github.com/1Panel-dev/1Panel/agent/cron" "github.com/1Panel-dev/1Panel/agent/cron"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n" "github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/init/app" "github.com/1Panel-dev/1Panel/agent/init/app"
"github.com/1Panel-dev/1Panel/agent/init/business" "github.com/1Panel-dev/1Panel/agent/init/business"
@ -39,11 +40,25 @@ func Start() {
server := &http.Server{ server := &http.Server{
Handler: rootRouter, Handler: rootRouter,
} }
if len(global.CurrentNode) == 0 || global.CurrentNode == "127.0.0.1" {
_ = os.Remove("/tmp/agent.sock") _ = os.Remove("/tmp/agent.sock")
listener, err := net.Listen("unix", "/tmp/agent.sock") listener, err := net.Listen("unix", "/tmp/agent.sock")
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = server.Serve(listener) _ = server.Serve(listener)
} else {
server.Addr = "0.0.0.0:9999"
type tcpKeepAliveListener struct {
*net.TCPListener
}
ln, err := net.Listen("tcp4", "0.0.0.0:9999")
if err != nil {
panic(err)
}
global.LOG.Info("listen at http://0.0.0.0:9999")
if err := server.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}); err != nil {
panic(err)
}
}
} }

View file

@ -3,4 +3,7 @@ package constant
const ( const (
StatusSuccess = "Success" StatusSuccess = "Success"
StatusFailed = "Failed" StatusFailed = "Failed"
StatusHealthy = "Healthy"
StatusUnhealthy = "Unhealthy"
) )

View file

@ -2,9 +2,11 @@ package middleware
import ( import (
"context" "context"
"fmt"
"net" "net"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url"
"os" "os"
"strings" "strings"
@ -19,6 +21,8 @@ func Proxy() gin.HandlerFunc {
c.Next() c.Next()
return return
} }
currentNode := c.Request.Header.Get("CurrentNode")
if currentNode == "127.0.0.1" {
sockPath := "/tmp/agent.sock" sockPath := "/tmp/agent.sock"
if _, err := os.Stat(sockPath); err != nil { if _, err := os.Stat(sockPath); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrProxy, err) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrProxy, err)
@ -41,5 +45,18 @@ func Proxy() gin.HandlerFunc {
} }
proxy.ServeHTTP(c.Writer, c.Request) proxy.ServeHTTP(c.Writer, c.Request)
c.Abort() c.Abort()
return
}
target, err := url.Parse(fmt.Sprintf("http://%s:9999", currentNode))
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrProxy, err)
return
}
proxy := httputil.NewSingleHostReverseProxy(target)
c.Request.Host = target.Host
c.Request.URL.Scheme = target.Scheme
c.Request.URL.Host = target.Host
proxy.ServeHTTP(c.Writer, c.Request)
c.Abort()
} }
} }

View file

@ -26,6 +26,7 @@ class RequestHttp {
'Accept-Language': language, 'Accept-Language': language,
...config.headers, ...config.headers,
}; };
config.headers.CurrentNode = globalStore.currentNode;
if (config.url === '/auth/login' || config.url === '/auth/mfalogin') { if (config.url === '/auth/login' || config.url === '/auth/mfalogin') {
let entrance = Base64.encode(globalStore.entrance); let entrance = Base64.encode(globalStore.entrance);
config.headers.EntranceCode = entrance; config.headers.EntranceCode = entrance;

View file

@ -7,6 +7,21 @@
element-loading-background="rgba(122, 122, 122, 0.01)" element-loading-background="rgba(122, 122, 122, 0.01)"
> >
<Logo :isCollapse="isCollapse" /> <Logo :isCollapse="isCollapse" />
<span v-if="nodes.length !== 1" class="el-dropdown-link">
{{ globalStore.currentNode || '127.0.0.1' }}
</span>
<el-dropdown v-if="nodes.length !== 1" placement="right-start" @command="changeNode">
<el-icon class="ico"><Switch /></el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="item in nodes" :key="item.name" :command="item.name">
{{ item.name }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-scrollbar> <el-scrollbar>
<el-menu <el-menu
:default-active="activeMenu" :default-active="activeMenu"
@ -50,6 +65,7 @@ import { getSettingInfo } from '@/api/modules/setting';
const route = useRoute(); const route = useRoute();
const menuStore = MenuStore(); const menuStore = MenuStore();
const globalStore = GlobalStore(); const globalStore = GlobalStore();
const nodes = ref([]);
defineProps({ defineProps({
menuRouter: { menuRouter: {
type: Boolean, type: Boolean,
@ -110,6 +126,30 @@ const systemLogOut = async () => {
await logOutApi(); await logOutApi();
}; };
const loadNodes = async () => {
if (globalStore.isProductPro) {
let listXNodes;
const xpackModules = import.meta.glob('../../../xpack/api/modules/node.ts', { eager: true });
if (xpackModules['../../../xpack/api/modules/node.ts']) {
console.log('dqwdqwd');
listXNodes = xpackModules['../../../xpack/api/modules/node.ts']['listNodes'] || {};
const res = await listXNodes();
if (!res) {
nodes.value = [];
return;
}
console.log('dqwdqwd');
nodes.value = res.data;
return;
}
nodes.value = [];
}
};
const changeNode = (command: string) => {
globalStore.currentNode = command || '127.0.0.1';
location.reload();
};
function extractLabels(node: Node, result: string[]): void { function extractLabels(node: Node, result: string[]): void {
if (node.isCheck) { if (node.isCheck) {
result.push(node.label); result.push(node.label);
@ -172,6 +212,7 @@ const search = async () => {
onMounted(() => { onMounted(() => {
menuStore.setMenuList(menuList); menuStore.setMenuList(menuList);
search(); search();
loadNodes();
}); });
</script> </script>
@ -194,4 +235,23 @@ onMounted(() => {
} }
} }
} }
.el-dropdown-link {
margin-top: -5px;
margin-left: 30px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
color: var(--el-color-primary);
display: flex;
align-items: center;
height: 28px;
}
.ico {
margin-top: -20px;
display: flex;
float: left;
position: absolute;
right: 25px;
}
</style> </style>

View file

@ -37,6 +37,8 @@ export interface GlobalState {
productProExpires: number; productProExpires: number;
errStatus: string; errStatus: string;
currentNode: string;
} }
export interface MenuState { export interface MenuState {

View file

@ -41,6 +41,8 @@ const GlobalStore = defineStore({
productProExpires: 0, productProExpires: 0,
errStatus: '', errStatus: '',
currentNode: '',
}), }),
getters: { getters: {
isDarkTheme: (state) => isDarkTheme: (state) =>