mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 07:57:21 +08:00
feat: compose接口
This commit is contained in:
@@ -97,6 +97,8 @@ func initWeb() (*app.Web, error) {
|
|||||||
sshService := service.NewSSHService(sshRepo)
|
sshService := service.NewSSHService(sshRepo)
|
||||||
containerRepo := data.NewContainerRepo()
|
containerRepo := data.NewContainerRepo()
|
||||||
containerService := service.NewContainerService(containerRepo)
|
containerService := service.NewContainerService(containerRepo)
|
||||||
|
containerComposeRepo := data.NewContainerComposeRepo()
|
||||||
|
containerComposeService := service.NewContainerComposeService(containerComposeRepo)
|
||||||
containerNetworkRepo := data.NewContainerNetworkRepo()
|
containerNetworkRepo := data.NewContainerNetworkRepo()
|
||||||
containerNetworkService := service.NewContainerNetworkService(containerNetworkRepo)
|
containerNetworkService := service.NewContainerNetworkService(containerNetworkRepo)
|
||||||
containerImageRepo := data.NewContainerImageRepo()
|
containerImageRepo := data.NewContainerImageRepo()
|
||||||
@@ -132,7 +134,7 @@ func initWeb() (*app.Web, error) {
|
|||||||
supervisorApp := supervisor.NewApp()
|
supervisorApp := supervisor.NewApp()
|
||||||
toolboxApp := toolbox.NewApp()
|
toolboxApp := toolbox.NewApp()
|
||||||
loader := bootstrap.NewLoader(benchmarkApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, mysqlApp, nginxApp, php74App, php80App, php81App, php82App, php83App, php84App, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp, toolboxApp)
|
loader := bootstrap.NewLoader(benchmarkApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, mysqlApp, nginxApp, php74App, php80App, php81App, php82App, php83App, php84App, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp, toolboxApp)
|
||||||
http := route.NewHttp(userService, dashboardService, taskService, websiteService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, cronService, processService, safeService, firewallService, sshService, containerService, containerNetworkService, containerImageService, containerVolumeService, fileService, monitorService, settingService, systemctlService, loader)
|
http := route.NewHttp(userService, dashboardService, taskService, websiteService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, cronService, processService, safeService, firewallService, sshService, containerService, containerComposeService, containerNetworkService, containerImageService, containerVolumeService, fileService, monitorService, settingService, systemctlService, loader)
|
||||||
wsService := service.NewWsService(koanf, sshRepo)
|
wsService := service.NewWsService(koanf, sshRepo)
|
||||||
ws := route.NewWs(wsService)
|
ws := route.NewWs(wsService)
|
||||||
mux, err := bootstrap.NewRouter(middlewares, http, ws)
|
mux, err := bootstrap.NewRouter(middlewares, http, ws)
|
||||||
|
|||||||
10
internal/biz/container_compose.go
Normal file
10
internal/biz/container_compose.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package biz
|
||||||
|
|
||||||
|
type ContainerComposeRepo interface {
|
||||||
|
List() ([]string, error)
|
||||||
|
Get(name string) (string, error)
|
||||||
|
Create(name, compose string) error
|
||||||
|
Up(name string, force bool) error
|
||||||
|
Down(name string) error
|
||||||
|
Remove(name string) error
|
||||||
|
}
|
||||||
83
internal/data/container_compose.go
Normal file
83
internal/data/container_compose.go
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tnb-labs/panel/internal/app"
|
||||||
|
"github.com/tnb-labs/panel/internal/biz"
|
||||||
|
"github.com/tnb-labs/panel/pkg/shell"
|
||||||
|
)
|
||||||
|
|
||||||
|
type containerComposeRepo struct{}
|
||||||
|
|
||||||
|
func NewContainerComposeRepo() biz.ContainerComposeRepo {
|
||||||
|
return &containerComposeRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// List 列出所有编排文件名
|
||||||
|
func (r *containerComposeRepo) List() ([]string, error) {
|
||||||
|
dir := filepath.Join(app.Root, "server", "compose")
|
||||||
|
var files []string
|
||||||
|
err := filepath.Walk(dir, func(path string, d fs.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if d.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if ext := filepath.Ext(path); ext == ".yml" || ext == ".yaml" {
|
||||||
|
files = append(files, strings.TrimSuffix(filepath.Base(path), ext))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 获取编排文件内容
|
||||||
|
func (r *containerComposeRepo) Get(name string) (string, error) {
|
||||||
|
dir := filepath.Join(app.Root, "server", "compose")
|
||||||
|
path := filepath.Join(dir, name+".yml")
|
||||||
|
content, err := os.ReadFile(path)
|
||||||
|
return string(content), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create 创建编排文件
|
||||||
|
func (r *containerComposeRepo) Create(name, compose string) error {
|
||||||
|
dir := filepath.Join(app.Root, "server", "compose")
|
||||||
|
path := filepath.Join(dir, name+".yml")
|
||||||
|
return os.WriteFile(path, []byte(compose), 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Up 启动编排
|
||||||
|
func (r *containerComposeRepo) Up(name string, force bool) error {
|
||||||
|
dir := filepath.Join(app.Root, "server", "compose")
|
||||||
|
path := filepath.Join(dir, name+".yml")
|
||||||
|
cmd := "docker compose -f %s up -d"
|
||||||
|
if force {
|
||||||
|
cmd += " --pull always" // 强制拉取镜像
|
||||||
|
}
|
||||||
|
_, err := shell.Execf(cmd, path)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Down 停止编排
|
||||||
|
func (r *containerComposeRepo) Down(name string) error {
|
||||||
|
dir := filepath.Join(app.Root, "server", "compose")
|
||||||
|
path := filepath.Join(dir, name+".yml")
|
||||||
|
_, err := shell.Execf("docker compose -f %s down", path)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove 删除编排
|
||||||
|
func (r *containerComposeRepo) Remove(name string) error {
|
||||||
|
dir := filepath.Join(app.Root, "server", "compose")
|
||||||
|
path := filepath.Join(dir, name+".yml")
|
||||||
|
return os.Remove(path)
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ var ProviderSet = wire.NewSet(
|
|||||||
NewCertAccountRepo,
|
NewCertAccountRepo,
|
||||||
NewCertDNSRepo,
|
NewCertDNSRepo,
|
||||||
NewContainerRepo,
|
NewContainerRepo,
|
||||||
|
NewContainerComposeRepo,
|
||||||
NewContainerImageRepo,
|
NewContainerImageRepo,
|
||||||
NewContainerNetworkRepo,
|
NewContainerNetworkRepo,
|
||||||
NewContainerVolumeRepo,
|
NewContainerVolumeRepo,
|
||||||
|
|||||||
23
internal/http/request/container_compose.go
Normal file
23
internal/http/request/container_compose.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package request
|
||||||
|
|
||||||
|
type ContainerComposeGet struct {
|
||||||
|
Name string `uri:"name" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainerComposeCreate struct {
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
Compose string `json:"compose" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainerComposeUp struct {
|
||||||
|
Name string `uri:"name" validate:"required"`
|
||||||
|
Force bool `json:"force"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainerComposeDown struct {
|
||||||
|
Name string `uri:"name" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainerComposeRemove struct {
|
||||||
|
Name string `uri:"name" validate:"required"`
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ type Http struct {
|
|||||||
firewall *service.FirewallService
|
firewall *service.FirewallService
|
||||||
ssh *service.SSHService
|
ssh *service.SSHService
|
||||||
container *service.ContainerService
|
container *service.ContainerService
|
||||||
|
containerCompose *service.ContainerComposeService
|
||||||
containerNetwork *service.ContainerNetworkService
|
containerNetwork *service.ContainerNetworkService
|
||||||
containerImage *service.ContainerImageService
|
containerImage *service.ContainerImageService
|
||||||
containerVolume *service.ContainerVolumeService
|
containerVolume *service.ContainerVolumeService
|
||||||
@@ -62,6 +63,7 @@ func NewHttp(
|
|||||||
firewall *service.FirewallService,
|
firewall *service.FirewallService,
|
||||||
ssh *service.SSHService,
|
ssh *service.SSHService,
|
||||||
container *service.ContainerService,
|
container *service.ContainerService,
|
||||||
|
containerCompose *service.ContainerComposeService,
|
||||||
containerNetwork *service.ContainerNetworkService,
|
containerNetwork *service.ContainerNetworkService,
|
||||||
containerImage *service.ContainerImageService,
|
containerImage *service.ContainerImageService,
|
||||||
containerVolume *service.ContainerVolumeService,
|
containerVolume *service.ContainerVolumeService,
|
||||||
@@ -90,6 +92,7 @@ func NewHttp(
|
|||||||
firewall: firewall,
|
firewall: firewall,
|
||||||
ssh: ssh,
|
ssh: ssh,
|
||||||
container: container,
|
container: container,
|
||||||
|
containerCompose: containerCompose,
|
||||||
containerNetwork: containerNetwork,
|
containerNetwork: containerNetwork,
|
||||||
containerImage: containerImage,
|
containerImage: containerImage,
|
||||||
containerVolume: containerVolume,
|
containerVolume: containerVolume,
|
||||||
@@ -284,6 +287,14 @@ func (route *Http) Register(r *chi.Mux) {
|
|||||||
r.Get("/{id}/logs", route.container.Logs)
|
r.Get("/{id}/logs", route.container.Logs)
|
||||||
r.Post("/prune", route.container.Prune)
|
r.Post("/prune", route.container.Prune)
|
||||||
})
|
})
|
||||||
|
r.Route("/compose", func(r chi.Router) {
|
||||||
|
r.Get("/", route.containerCompose.List)
|
||||||
|
r.Get("/{name}", route.containerCompose.Get)
|
||||||
|
r.Post("/", route.containerCompose.Create)
|
||||||
|
r.Post("/{name}/up", route.containerCompose.Up)
|
||||||
|
r.Post("/{name}/down", route.containerCompose.Down)
|
||||||
|
r.Delete("/{name}", route.containerCompose.Remove)
|
||||||
|
})
|
||||||
r.Route("/network", func(r chi.Router) {
|
r.Route("/network", func(r chi.Router) {
|
||||||
r.Get("/", route.containerNetwork.List)
|
r.Get("/", route.containerNetwork.List)
|
||||||
r.Post("/", route.containerNetwork.Create)
|
r.Post("/", route.containerNetwork.Create)
|
||||||
|
|||||||
111
internal/service/container_compose.go
Normal file
111
internal/service/container_compose.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-rat/chix"
|
||||||
|
|
||||||
|
"github.com/tnb-labs/panel/internal/biz"
|
||||||
|
"github.com/tnb-labs/panel/internal/http/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ContainerComposeService struct {
|
||||||
|
containerComposeRepo biz.ContainerComposeRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewContainerComposeService(containerCompose biz.ContainerComposeRepo) *ContainerComposeService {
|
||||||
|
return &ContainerComposeService{
|
||||||
|
containerComposeRepo: containerCompose,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ContainerComposeService) List(w http.ResponseWriter, r *http.Request) {
|
||||||
|
files, err := s.containerComposeRepo.List()
|
||||||
|
if err != nil {
|
||||||
|
Error(w, http.StatusInternalServerError, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
paged, total := Paginate(r, files)
|
||||||
|
|
||||||
|
Success(w, chix.M{
|
||||||
|
"total": total,
|
||||||
|
"items": paged,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ContainerComposeService) Get(w http.ResponseWriter, r *http.Request) {
|
||||||
|
req, err := Bind[request.ContainerComposeGet](r)
|
||||||
|
if err != nil {
|
||||||
|
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := s.containerComposeRepo.Get(req.Name)
|
||||||
|
if err != nil {
|
||||||
|
Error(w, http.StatusInternalServerError, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Success(w, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ContainerComposeService) Create(w http.ResponseWriter, r *http.Request) {
|
||||||
|
req, err := Bind[request.ContainerComposeCreate](r)
|
||||||
|
if err != nil {
|
||||||
|
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = s.containerComposeRepo.Create(req.Name, req.Compose); err != nil {
|
||||||
|
Error(w, http.StatusInternalServerError, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Success(w, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ContainerComposeService) Up(w http.ResponseWriter, r *http.Request) {
|
||||||
|
req, err := Bind[request.ContainerComposeUp](r)
|
||||||
|
if err != nil {
|
||||||
|
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = s.containerComposeRepo.Up(req.Name, req.Force); err != nil {
|
||||||
|
Error(w, http.StatusInternalServerError, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Success(w, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ContainerComposeService) Down(w http.ResponseWriter, r *http.Request) {
|
||||||
|
req, err := Bind[request.ContainerComposeDown](r)
|
||||||
|
if err != nil {
|
||||||
|
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = s.containerComposeRepo.Down(req.Name); err != nil {
|
||||||
|
Error(w, http.StatusInternalServerError, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Success(w, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ContainerComposeService) Remove(w http.ResponseWriter, r *http.Request) {
|
||||||
|
req, err := Bind[request.ContainerComposeRemove](r)
|
||||||
|
if err != nil {
|
||||||
|
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = s.containerComposeRepo.Remove(req.Name); err != nil {
|
||||||
|
Error(w, http.StatusInternalServerError, "%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Success(w, nil)
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ var ProviderSet = wire.NewSet(
|
|||||||
NewCertDNSService,
|
NewCertDNSService,
|
||||||
NewCliService,
|
NewCliService,
|
||||||
NewContainerService,
|
NewContainerService,
|
||||||
|
NewContainerComposeService,
|
||||||
NewContainerImageService,
|
NewContainerImageService,
|
||||||
NewContainerNetworkService,
|
NewContainerNetworkService,
|
||||||
NewContainerVolumeService,
|
NewContainerVolumeService,
|
||||||
|
|||||||
Reference in New Issue
Block a user