mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-09-08 15:44:55 +08:00
fix: 解决删除网站导致的数据库锁库问题
This commit is contained in:
parent
94ebe4952a
commit
0a8bf98ee9
12 changed files with 66 additions and 57 deletions
|
@ -1,6 +1,7 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
|
@ -63,7 +64,7 @@ func (b *BaseApi) InstallApp(c *gin.Context) {
|
|||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
install, err := appService.Install(req.Name, req.AppDetailId, req.Params)
|
||||
install, err := appService.Install(context.Background(), req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
|
@ -18,7 +19,7 @@ func (b *BaseApi) CreateMysql(c *gin.Context) {
|
|||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := mysqlService.Create(req); err != nil {
|
||||
if _, err := mysqlService.Create(context.Background(), req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"gorm.io/gorm"
|
||||
|
@ -17,7 +18,7 @@ type IBackupRepo interface {
|
|||
CreateRecord(record *model.BackupRecord) error
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
DeleteRecord(opts ...DBOption) error
|
||||
DeleteRecord(ctx context.Context, opts ...DBOption) error
|
||||
WithByDetailName(detailName string) DBOption
|
||||
}
|
||||
|
||||
|
@ -114,10 +115,6 @@ func (u *BackupRepo) Delete(opts ...DBOption) error {
|
|||
return db.Delete(&model.BackupAccount{}).Error
|
||||
}
|
||||
|
||||
func (u *BackupRepo) DeleteRecord(opts ...DBOption) error {
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
return db.Delete(&model.BackupRecord{}).Error
|
||||
func (u *BackupRepo) DeleteRecord(ctx context.Context, opts ...DBOption) error {
|
||||
return getTx(ctx, opts...).Delete(&model.BackupRecord{}).Error
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
|
@ -25,7 +26,6 @@ type AppService struct {
|
|||
}
|
||||
|
||||
func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
|
||||
|
||||
var opts []repo.DBOption
|
||||
opts = append(opts, commonRepo.WithOrderBy("name"))
|
||||
if req.Name != "" {
|
||||
|
@ -139,22 +139,21 @@ func (a AppService) GetAppDetail(appId uint, version string) (response.AppDetail
|
|||
return appDetailDTO, nil
|
||||
}
|
||||
|
||||
func (a AppService) Install(name string, appDetailId uint, params map[string]interface{}) (*model.AppInstall, error) {
|
||||
|
||||
if list, _ := appInstallRepo.GetBy(commonRepo.WithByName(name)); len(list) > 0 {
|
||||
func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) {
|
||||
if list, _ := appInstallRepo.GetBy(commonRepo.WithByName(req.Name)); len(list) > 0 {
|
||||
return nil, buserr.New(constant.ErrNameIsExist)
|
||||
}
|
||||
|
||||
httpPort, err := checkPort("PANEL_APP_PORT_HTTP", params)
|
||||
httpPort, err := checkPort("PANEL_APP_PORT_HTTP", req.Params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
httpsPort, err := checkPort("PANEL_APP_PORT_HTTPS", params)
|
||||
httpsPort, err := checkPort("PANEL_APP_PORT_HTTPS", req.Params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(appDetailId))
|
||||
appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(req.AppDetailId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -166,16 +165,16 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int
|
|||
if err := checkRequiredAndLimit(app); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := copyAppData(app.Key, appDetail.Version, name, params); err != nil {
|
||||
if err := copyAppData(app.Key, appDetail.Version, req.Name, req.Params); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
paramByte, err := json.Marshal(params)
|
||||
paramByte, err := json.Marshal(req.Params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appInstall := model.AppInstall{
|
||||
Name: name,
|
||||
Name: req.Name,
|
||||
AppId: appDetail.AppId,
|
||||
AppDetailId: appDetail.ID,
|
||||
Version: appDetail.Version,
|
||||
|
@ -216,12 +215,12 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int
|
|||
return nil, err
|
||||
}
|
||||
|
||||
tx, ctx := getTxAndContext()
|
||||
tx, ctx := getTxByContext(ctx)
|
||||
if err := appInstallRepo.Create(ctx, &appInstall); err != nil {
|
||||
tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
if err := createLink(ctx, app, &appInstall, params); err != nil {
|
||||
if err := createLink(ctx, app, &appInstall, req.Params); err != nil {
|
||||
tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
@ -484,20 +483,16 @@ func (a AppService) SyncAppList() error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := appTagRepo.DeleteAll(ctx); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
if len(appTags) > 0 {
|
||||
if err := appTagRepo.BatchCreate(ctx, appTags); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
tx.Commit()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -130,29 +130,25 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var database model.DatabaseMysql
|
||||
database.Name = dbConfig.DbName
|
||||
database.Username = dbConfig.DbUser
|
||||
database.Password = dbConfig.Password
|
||||
database.MysqlName = dbInstall.Name
|
||||
database.Format = "utf8mb4"
|
||||
database.Permission = "127.0.0.1"
|
||||
if err := mysqlRepo.Create(ctx, &database); err != nil {
|
||||
var createMysql dto.MysqlDBCreate
|
||||
createMysql.Name = dbConfig.DbName
|
||||
createMysql.Username = dbConfig.DbUser
|
||||
createMysql.Format = "utf8mb4"
|
||||
createMysql.Permission = "%"
|
||||
createMysql.Password = dbConfig.Password
|
||||
mysqldb, err := NewIMysqlService().Create(ctx, createMysql)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var installResource model.AppInstallResource
|
||||
installResource.ResourceId = database.ID
|
||||
installResource.ResourceId = mysqldb.ID
|
||||
installResource.AppInstallId = appInstall.ID
|
||||
installResource.LinkId = dbInstall.ID
|
||||
installResource.Key = dbInstall.App.Key
|
||||
if err := appInstallResourceRepo.Create(ctx, &installResource); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := execDockerCommand(database, dbInstall, Add); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
@ -169,7 +170,7 @@ func (u *BackupService) BatchDeleteRecord(ids []uint) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
return backupRepo.DeleteRecord(commonRepo.WithIdsIn(ids))
|
||||
return backupRepo.DeleteRecord(context.Background(), commonRepo.WithIdsIn(ids))
|
||||
}
|
||||
|
||||
func (u *BackupService) Update(id uint, upMap map[string]interface{}) error {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -184,7 +185,7 @@ func (u *CronjobService) HandleRmExpired(backType, baseDir, backupDir string, cr
|
|||
dbCopies++
|
||||
if dbCopies > cronjob.RetainCopies {
|
||||
_ = os.Remove(baseDir + "/" + backupDir + "/" + files[i].Name())
|
||||
_ = backupRepo.DeleteRecord(backupRepo.WithByFileName(files[i].Name()))
|
||||
_ = backupRepo.DeleteRecord(context.Background(), backupRepo.WithByFileName(files[i].Name()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ type MysqlService struct{}
|
|||
type IMysqlService interface {
|
||||
SearchWithPage(search dto.PageInfo) (int64, interface{}, error)
|
||||
ListDBName() ([]string, error)
|
||||
Create(mysqlDto dto.MysqlDBCreate) error
|
||||
Create(ctx context.Context, mysqlDto dto.MysqlDBCreate) (*model.DatabaseMysql, error)
|
||||
ChangeAccess(info dto.ChangeDBInfo) error
|
||||
ChangePassword(info dto.ChangeDBInfo) error
|
||||
UpdateVariables(updatas []dto.MysqlVariablesUpdate) error
|
||||
|
@ -153,41 +153,41 @@ func (u *MysqlService) ListDBName() ([]string, error) {
|
|||
return dbNames, err
|
||||
}
|
||||
|
||||
func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error {
|
||||
func (u *MysqlService) Create(ctx context.Context, mysqlDto dto.MysqlDBCreate) (*model.DatabaseMysql, error) {
|
||||
if mysqlDto.Username == "root" {
|
||||
return errors.New("Cannot set root as user name")
|
||||
return nil, errors.New("Cannot set root as user name")
|
||||
}
|
||||
app, err := appInstallRepo.LoadBaseInfo("mysql", "")
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
mysql, _ := mysqlRepo.Get(commonRepo.WithByName(mysqlDto.Name))
|
||||
if mysql.ID != 0 {
|
||||
return constant.ErrRecordExist
|
||||
return nil, constant.ErrRecordExist
|
||||
}
|
||||
if err := copier.Copy(&mysql, &mysqlDto); err != nil {
|
||||
return errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
|
||||
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create database if not exists `%s` character set=%s", mysqlDto.Name, mysqlDto.Format)); err != nil {
|
||||
return err
|
||||
return nil,err
|
||||
}
|
||||
tmpPermission := mysqlDto.Permission
|
||||
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create user if not exists '%s'@'%s' identified by '%s';", mysqlDto.Username, tmpPermission, mysqlDto.Password)); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to '%s'@'%s'", mysqlDto.Name, mysqlDto.Username, tmpPermission)
|
||||
if app.Version == "5.7.39" {
|
||||
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysqlDto.Password)
|
||||
}
|
||||
if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
mysql.MysqlName = app.Name
|
||||
if err := mysqlRepo.Create(context.TODO(), &mysql); err != nil {
|
||||
return err
|
||||
if err := mysqlRepo.Create(ctx, &mysql); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
return &mysql, nil
|
||||
}
|
||||
|
||||
func (u *MysqlService) Backup(db dto.BackupDB) error {
|
||||
|
@ -281,7 +281,7 @@ func (u *MysqlService) Delete(id uint) error {
|
|||
if _, err := os.Stat(backupDir); err == nil {
|
||||
_ = os.RemoveAll(backupDir)
|
||||
}
|
||||
_ = backupRepo.DeleteRecord(commonRepo.WithByType("database-mysql"), commonRepo.WithByName(app.Name), backupRepo.WithByDetailName(db.Name))
|
||||
_ = backupRepo.DeleteRecord(context.Background(), commonRepo.WithByType("database-mysql"), commonRepo.WithByName(app.Name), backupRepo.WithByDetailName(db.Name))
|
||||
|
||||
_ = mysqlRepo.Delete(context.Background(), commonRepo.WithByID(db.ID))
|
||||
return nil
|
||||
|
|
|
@ -12,3 +12,13 @@ func getTxAndContext() (tx *gorm.DB, ctx context.Context) {
|
|||
ctx = context.WithValue(context.Background(), constant.DB, tx)
|
||||
return
|
||||
}
|
||||
|
||||
func getTxByContext(ctx context.Context) (*gorm.DB, context.Context) {
|
||||
tx, ok := ctx.Value(constant.DB).(*gorm.DB)
|
||||
if ok {
|
||||
return tx, ctx
|
||||
}
|
||||
tx = global.DB.Begin()
|
||||
ctx = context.WithValue(context.Background(), constant.DB, tx)
|
||||
return tx, ctx
|
||||
}
|
||||
|
|
|
@ -95,7 +95,11 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) error {
|
|||
switch create.Type {
|
||||
case constant.Deployment:
|
||||
if create.AppType == constant.NewApp {
|
||||
install, err := ServiceGroupApp.Install(create.AppInstall.Name, create.AppInstall.AppDetailId, create.AppInstall.Params)
|
||||
var req request.AppInstallCreate
|
||||
req.Name = create.AppInstall.Name
|
||||
req.AppDetailId = create.AppInstall.AppDetailId
|
||||
req.Params = create.AppInstall.Params
|
||||
install, err := ServiceGroupApp.Install(context.Background(), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -275,9 +279,10 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error {
|
|||
for _, b := range backups {
|
||||
_ = fileOp.DeleteDir(b.FileDir)
|
||||
}
|
||||
}
|
||||
if err := backupRepo.DeleteRecord(backupRepo.WithByType("website-"+website.Type), commonRepo.WithByName(website.PrimaryDomain)); err != nil {
|
||||
return err
|
||||
if err := backupRepo.DeleteRecord(ctx, backupRepo.WithByType("website-"+website.Type), commonRepo.WithByName(website.PrimaryDomain)); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ const acceptParams = async (app: App.AppInstalled) => {
|
|||
deleteBackup: false,
|
||||
forceDelete: false,
|
||||
};
|
||||
deleteInfo.value = '';
|
||||
deleteReq.value.installId = app.id;
|
||||
deleteHelper.value = i18n.global.t('website.deleteConfirmHelper', [app.name]);
|
||||
appInstallName.value = app.name;
|
||||
|
|
|
@ -90,6 +90,7 @@ const acceptParams = async (website: Website.Website) => {
|
|||
deleteBackup: false,
|
||||
forceDelete: false,
|
||||
};
|
||||
deleteInfo.value = '';
|
||||
deleteReq.value.id = website.id;
|
||||
websiteName.value = website.primaryDomain;
|
||||
deleteHelper.value = i18n.global.t('website.deleteConfirmHelper', [website.primaryDomain]);
|
||||
|
|
Loading…
Add table
Reference in a new issue