1Panel/backend/app/service/runtime.go
2023-04-06 10:38:14 +08:00

158 lines
4.2 KiB
Go

package service
import (
"context"
"fmt"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/app/repo"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/subosito/gotenv"
"path"
"path/filepath"
"time"
)
type RuntimeService struct {
}
type IRuntimeService interface {
Page(req request.RuntimeSearch) (int64, []response.RuntimeRes, error)
Create(create request.RuntimeCreate) error
Delete(id uint) error
}
func NewRuntimeService() IRuntimeService {
return &RuntimeService{}
}
func (r *RuntimeService) Create(create request.RuntimeCreate) error {
if create.Resource == constant.ResourceLocal {
runtime := &model.Runtime{
Name: create.Name,
Resource: create.Resource,
Type: create.Type,
Status: constant.RuntimeNormal,
}
return runtimeRepo.Create(context.Background(), runtime)
}
var err error
appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(create.AppDetailID))
if err != nil {
return err
}
app, err := appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId))
if err != nil {
return err
}
fileOp := files.NewFileOp()
buildDir := path.Join(constant.AppResourceDir, app.Key, "versions", appDetail.Version, "build")
if !fileOp.Stat(buildDir) {
return buserr.New(constant.ErrDirNotFound)
}
runtimeDir := path.Join(constant.RuntimeDir, create.Type)
tempDir := filepath.Join(runtimeDir, fmt.Sprintf("%d", time.Now().UnixNano()))
if err := fileOp.CopyDir(buildDir, tempDir); err != nil {
return err
}
oldDir := path.Join(tempDir, "build")
newNameDir := path.Join(runtimeDir, create.Name)
defer func() {
if err != nil {
_ = fileOp.DeleteDir(newNameDir)
}
}()
if oldDir != newNameDir {
if err := fileOp.Rename(oldDir, newNameDir); err != nil {
return err
}
if err := fileOp.DeleteDir(tempDir); err != nil {
return err
}
}
composeFile, err := fileOp.GetContent(path.Join(newNameDir, "docker-compose.yml"))
if err != nil {
return err
}
env, err := gotenv.Read(path.Join(newNameDir, ".env"))
if err != nil {
return err
}
newMap := make(map[string]string)
handleMap(create.Params, newMap)
for k, v := range newMap {
env[k] = v
}
envStr, err := gotenv.Marshal(env)
if err != nil {
return err
}
if err := gotenv.Write(env, path.Join(newNameDir, ".env")); err != nil {
return err
}
project, err := docker.GetComposeProject(create.Name, newNameDir, composeFile, []byte(envStr))
if err != nil {
return err
}
composeService, err := docker.NewComposeService()
if err != nil {
return err
}
composeService.SetProject(project)
runtime := &model.Runtime{
Name: create.Name,
DockerCompose: string(composeFile),
Env: envStr,
AppDetailID: create.AppDetailID,
Type: create.Type,
Image: create.Image,
Resource: create.Resource,
Status: constant.RuntimeBuildIng,
Version: create.Version,
}
if err := runtimeRepo.Create(context.Background(), runtime); err != nil {
return err
}
go buildRuntime(runtime, composeService)
return nil
}
func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.RuntimeRes, error) {
var (
opts []repo.DBOption
res []response.RuntimeRes
)
if req.Name != "" {
opts = append(opts, commonRepo.WithLikeName(req.Name))
}
total, runtimes, err := runtimeRepo.Page(req.Page, req.PageSize, opts...)
if err != nil {
return 0, nil, err
}
for _, runtime := range runtimes {
res = append(res, response.RuntimeRes{
Runtime: runtime,
})
}
return total, res, nil
}
func (r *RuntimeService) Delete(id uint) error {
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(id))
if err != nil {
return err
}
//TODO 校验网站关联
if runtime.Resource == constant.ResourceAppstore {
runtimeDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name)
if err := files.NewFileOp().DeleteDir(runtimeDir); err != nil {
return err
}
}
return runtimeRepo.DeleteBy(commonRepo.WithByID(id))
}