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 @@ - + + +