From 7fb42d7b47ab1b48c6ffbb59ba4317b12896bf1a Mon Sep 17 00:00:00 2001
From: zhengkunwang <31820853+zhengkunwang223@users.noreply.github.com>
Date: Fri, 16 Aug 2024 18:09:00 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B4=9F=E8=BD=BD=E5=9D=87=E8=A1=A1?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=BA=90=E6=96=87=E7=BC=96=E8=BE=91=20(#6153?=
=?UTF-8?q?)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
agent/app/api/v2/website.go | 40 +++++++
agent/app/dto/nginx.go | 1 +
agent/app/dto/request/website.go | 13 +++
agent/app/service/website.go | 110 +++++++++++++++++-
agent/router/ro_website.go | 2 +
agent/utils/nginx/components/upstream.go | 6 +-
frontend/src/api/interface/website.ts | 14 +++
frontend/src/api/modules/website.ts | 8 ++
.../config/basic/load-balance/file/index.vue | 67 +++++++++++
.../config/basic/load-balance/index.vue | 58 ++++++++-
.../basic/load-balance/operate/index.vue | 63 +++++++---
11 files changed, 361 insertions(+), 21 deletions(-)
create mode 100644 frontend/src/views/website/website/config/basic/load-balance/file/index.vue
diff --git a/agent/app/api/v2/website.go b/agent/app/api/v2/website.go
index df27953c9..035cdc38b 100644
--- a/agent/app/api/v2/website.go
+++ b/agent/app/api/v2/website.go
@@ -917,3 +917,43 @@ func (b *BaseApi) DeleteLoadBalance(c *gin.Context) {
}
helper.SuccessWithOutData(c)
}
+
+// @Tags Website
+// @Summary Update website upstream
+// @Description 更新网站 upstream
+// @Accept json
+// @Param request body request.WebsiteLBUpdate true "request"
+// @Success 200
+// @Security ApiKeyAuth
+// @Router /websites/lbs/update [post]
+func (b *BaseApi) UpdateLoadBalance(c *gin.Context) {
+ var req request.WebsiteLBUpdate
+ if err := helper.CheckBindAndValidate(&req, c); err != nil {
+ return
+ }
+ if err := websiteService.UpdateLoadBalance(req); err != nil {
+ helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
+ return
+ }
+ helper.SuccessWithOutData(c)
+}
+
+// @Tags Website
+// @Summary Update website upstream file
+// @Description 更新网站 upstream 文件
+// @Accept json
+// @Param request body request.WebsiteLBUpdateFile true "request"
+// @Success 200
+// @Security ApiKeyAuth
+// @Router /websites/lbs/file [post]
+func (b *BaseApi) UpdateLoadBalanceFile(c *gin.Context) {
+ var req request.WebsiteLBUpdateFile
+ if err := helper.CheckBindAndValidate(&req, c); err != nil {
+ return
+ }
+ if err := websiteService.UpdateLoadBalanceFile(req); err != nil {
+ helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
+ return
+ }
+ helper.SuccessWithOutData(c)
+}
diff --git a/agent/app/dto/nginx.go b/agent/app/dto/nginx.go
index 26627a29f..6b3927878 100644
--- a/agent/app/dto/nginx.go
+++ b/agent/app/dto/nginx.go
@@ -69,6 +69,7 @@ type NginxUpstream struct {
Name string `json:"name"`
Algorithm string `json:"algorithm"`
Servers []NginxUpstreamServer `json:"servers"`
+ Content string `json:"content"`
}
type NginxUpstreamServer struct {
diff --git a/agent/app/dto/request/website.go b/agent/app/dto/request/website.go
index 674042d42..1fef31e04 100644
--- a/agent/app/dto/request/website.go
+++ b/agent/app/dto/request/website.go
@@ -264,7 +264,20 @@ type WebsiteLBCreate struct {
Servers []dto.NginxUpstreamServer `json:"servers"`
}
+type WebsiteLBUpdate struct {
+ WebsiteID uint `json:"websiteID" validate:"required"`
+ Name string `json:"name" validate:"required"`
+ Algorithm string `json:"algorithm"`
+ Servers []dto.NginxUpstreamServer `json:"servers"`
+}
+
type WebsiteLBDelete struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Name string `json:"name" validate:"required"`
}
+
+type WebsiteLBUpdateFile struct {
+ WebsiteID uint `json:"websiteID" validate:"required"`
+ Name string `json:"name" validate:"required"`
+ Content string `json:"content" validate:"required"`
+}
diff --git a/agent/app/service/website.go b/agent/app/service/website.go
index 29f2f1eaa..c82162354 100644
--- a/agent/app/service/website.go
+++ b/agent/app/service/website.go
@@ -112,6 +112,8 @@ type IWebsiteService interface {
GetLoadBalances(id uint) ([]dto.NginxUpstream, error)
CreateLoadBalance(req request.WebsiteLBCreate) error
DeleteLoadBalance(req request.WebsiteLBDelete) error
+ UpdateLoadBalance(req request.WebsiteLBUpdate) error
+ UpdateLoadBalanceFile(req request.WebsiteLBUpdateFile) error
}
func NewIWebsiteService() IWebsiteService {
@@ -2934,6 +2936,11 @@ func (w WebsiteService) GetLoadBalances(id uint) ([]dto.NginxUpstream, error) {
Name: upstreamName,
}
upstreamPath := path.Join(includeDir, name)
+ content, err := fileOp.GetContent(upstreamPath)
+ if err != nil {
+ return nil, err
+ }
+ upstream.Content = string(content)
nginxParser, err := parser.NewParser(upstreamPath)
if err != nil {
return nil, err
@@ -3019,6 +3026,9 @@ func (w WebsiteService) CreateLoadBalance(req request.WebsiteLBCreate) error {
upstream := components.Upstream{
UpstreamName: req.Name,
}
+ if req.Algorithm != "default" {
+ upstream.UpdateDirective(req.Algorithm, []string{})
+ }
servers := make([]*components.UpstreamServer, 0)
@@ -3064,6 +3074,78 @@ func (w WebsiteService) CreateLoadBalance(req request.WebsiteLBCreate) error {
return nil
}
+func (w WebsiteService) UpdateLoadBalance(req request.WebsiteLBUpdate) error {
+ website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
+ if err != nil {
+ return err
+ }
+ nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
+ if err != nil {
+ return err
+ }
+ includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "upstream")
+ fileOp := files.NewFileOp()
+ filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
+ if !fileOp.Stat(filePath) {
+ return nil
+ }
+ parser, err := parser.NewParser(filePath)
+ if err != nil {
+ return err
+ }
+ config, err := parser.Parse()
+ if err != nil {
+ return err
+ }
+ upstreams := config.FindUpstreams()
+ for _, up := range upstreams {
+ if up.UpstreamName == req.Name {
+ directives := up.GetDirectives()
+ for _, d := range directives {
+ dName := d.GetName()
+ if _, ok := dto.LBAlgorithms[dName]; ok {
+ up.RemoveDirective(dName, nil)
+ }
+ }
+ if req.Algorithm != "default" {
+ up.UpdateDirective(req.Algorithm, []string{})
+ }
+ var servers []*components.UpstreamServer
+ for _, server := range req.Servers {
+ upstreamServer := &components.UpstreamServer{
+ Address: server.Server,
+ }
+ parameters := make(map[string]string)
+ if server.Weight > 0 {
+ parameters["weight"] = strconv.Itoa(server.Weight)
+ }
+ if server.MaxFails > 0 {
+ parameters["max_fails"] = strconv.Itoa(server.MaxFails)
+ }
+ if server.FailTimeout != "" {
+ parameters["fail_timeout"] = server.FailTimeout
+ }
+ if server.MaxConns > 0 {
+ parameters["max_conns"] = strconv.Itoa(server.MaxConns)
+ }
+ if server.Flag != "" {
+ upstreamServer.Flags = []string{server.Flag}
+ }
+ upstreamServer.Parameters = parameters
+ servers = append(servers, upstreamServer)
+ }
+ up.UpstreamServers = servers
+ }
+ }
+ if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
+ return buserr.WithErr(constant.ErrUpdateBuWebsite, err)
+ }
+ if err = opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
+ return err
+ }
+ return nil
+}
+
func (w WebsiteService) DeleteLoadBalance(req request.WebsiteLBDelete) error {
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
if err != nil {
@@ -3082,8 +3164,32 @@ func (w WebsiteService) DeleteLoadBalance(req request.WebsiteLBDelete) error {
if err = fileOp.DeleteFile(filePath); err != nil {
return err
}
- if err = opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
+ return opNginx(nginxInstall.ContainerName, constant.NginxReload)
+}
+
+func (w WebsiteService) UpdateLoadBalanceFile(req request.WebsiteLBUpdateFile) error {
+ website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
+ if err != nil {
return err
}
- return nil
+ nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
+ if err != nil {
+ return err
+ }
+ includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "upstream")
+ filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
+ fileOp := files.NewFileOp()
+ oldContent, err := fileOp.GetContent(filePath)
+ if err != nil {
+ return err
+ }
+ if err = fileOp.WriteFile(filePath, strings.NewReader(req.Content), 0755); err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ _ = fileOp.WriteFile(filePath, bytes.NewReader(oldContent), 0755)
+ }
+ }()
+ return opNginx(nginxInstall.ContainerName, constant.NginxReload)
}
diff --git a/agent/router/ro_website.go b/agent/router/ro_website.go
index f5df8a7f9..35050c89f 100644
--- a/agent/router/ro_website.go
+++ b/agent/router/ro_website.go
@@ -72,5 +72,7 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
websiteRouter.GET("/:id/lbs", baseApi.GetLoadBalances)
websiteRouter.POST("/lbs/create", baseApi.CreateLoadBalance)
websiteRouter.POST("/lbs/del", baseApi.DeleteLoadBalance)
+ websiteRouter.POST("/lbs/update", baseApi.UpdateLoadBalance)
+ websiteRouter.POST("/lbs/file", baseApi.UpdateLoadBalanceFile)
}
}
diff --git a/agent/utils/nginx/components/upstream.go b/agent/utils/nginx/components/upstream.go
index 68e26d42d..1b0c0d518 100644
--- a/agent/utils/nginx/components/upstream.go
+++ b/agent/utils/nginx/components/upstream.go
@@ -82,10 +82,10 @@ func (us *Upstream) FindDirectives(directiveName string) []IDirective {
}
func (us *Upstream) UpdateDirective(key string, params []string) {
- if key == "" || len(params) == 0 {
+ if key == "" {
return
}
- directives := us.GetDirectives()
+ directives := us.Directives
index := -1
for i, dir := range directives {
if dir.GetName() == key {
@@ -112,7 +112,7 @@ func (us *Upstream) UpdateDirective(key string, params []string) {
}
func (us *Upstream) RemoveDirective(key string, params []string) {
- directives := us.GetDirectives()
+ directives := us.Directives
var newDirectives []IDirective
for _, dir := range directives {
if dir.GetName() == key {
diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts
index 1cf34dd2f..27426568d 100644
--- a/frontend/src/api/interface/website.ts
+++ b/frontend/src/api/interface/website.ts
@@ -573,6 +573,14 @@ export namespace Website {
name: string;
algorithm: string;
servers: NginxUpstreamServer[];
+ content?: string;
+ websiteID?: number;
+ }
+
+ export interface NginxUpstreamFile {
+ name: string;
+ content: string;
+ websiteID: number;
}
export interface LoadBalanceReq {
@@ -595,4 +603,10 @@ export namespace Website {
websiteID: number;
name: string;
}
+
+ export interface WebsiteLBUpdateFile {
+ websiteID: number;
+ name: string;
+ content: string;
+ }
}
diff --git a/frontend/src/api/modules/website.ts b/frontend/src/api/modules/website.ts
index 1b35b9449..773cd1da1 100644
--- a/frontend/src/api/modules/website.ts
+++ b/frontend/src/api/modules/website.ts
@@ -307,3 +307,11 @@ export const CreateLoadBalance = (req: Website.LoadBalanceReq) => {
export const DeleteLoadBalance = (req: Website.LoadBalanceDel) => {
return http.post(`/websites/lbs/del`, req);
};
+
+export const UpdateLoadBalance = (req: Website.LoadBalanceReq) => {
+ return http.post(`/websites/lbs/update`, req);
+};
+
+export const UpdateLoadBalanceFile = (req: Website.WebsiteLBUpdateFile) => {
+ return http.post(`/websites/lbs/file`, req);
+};
diff --git a/frontend/src/views/website/website/config/basic/load-balance/file/index.vue b/frontend/src/views/website/website/config/basic/load-balance/file/index.vue
new file mode 100644
index 000000000..d60e40fc9
--- /dev/null
+++ b/frontend/src/views/website/website/config/basic/load-balance/file/index.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/website/website/config/basic/load-balance/index.vue b/frontend/src/views/website/website/config/basic/load-balance/index.vue
index f211b5806..e3eb61449 100644
--- a/frontend/src/views/website/website/config/basic/load-balance/index.vue
+++ b/frontend/src/views/website/website/config/basic/load-balance/index.vue
@@ -7,7 +7,11 @@
-
+
+
+ {{ getAlgorithm(row.algorithm) }}
+
+
@@ -45,8 +49,9 @@
/>
-
+
+