mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 00:09:16 +08:00
fix: 计划任务数据库选项增加前缀 (#1820)
This commit is contained in:
parent
df770460d6
commit
a031d3ba41
@ -216,11 +216,11 @@ func (b *BaseApi) SearchMysql(c *gin.Context) {
|
||||
// @Description 获取 mysql 数据库列表
|
||||
// @Accept json
|
||||
// @Param request body dto.PageInfo true "request"
|
||||
// @Success 200 {array} string
|
||||
// @Success 200 {array} dto.MysqlOption
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/options [get]
|
||||
func (b *BaseApi) ListDBName(c *gin.Context) {
|
||||
list, err := mysqlService.ListDBName()
|
||||
list, err := mysqlService.ListDBOption()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
|
@ -24,6 +24,12 @@ type MysqlDBInfo struct {
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type MysqlOption struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
From string `json:"from"`
|
||||
}
|
||||
|
||||
type MysqlDBCreate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
From string `json:"from" validate:"required"`
|
||||
|
@ -110,7 +110,7 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string) erro
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := handleMysqlBackup(db.Name, tmpDir, fmt.Sprintf("%s.sql.gz", install.Name)); err != nil {
|
||||
if err := handleMysqlBackup(db.MysqlName, db.Name, tmpDir, fmt.Sprintf("%s.sql.gz", install.Name)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
|
||||
targetDir := path.Join(localDir, fmt.Sprintf("database/mysql/%s/%s", req.Name, req.DetailName))
|
||||
fileName := fmt.Sprintf("%s_%s.sql.gz", req.DetailName, timeNow)
|
||||
|
||||
if err := handleMysqlBackup(req.DetailName, targetDir, fileName); err != nil {
|
||||
if err := handleMysqlBackup(req.Name, req.DetailName, targetDir, fileName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -97,8 +97,8 @@ func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleMysqlBackup(dbName, targetDir, fileName string) error {
|
||||
dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(dbName))
|
||||
func handleMysqlBackup(name, dbName, targetDir, fileName string) error {
|
||||
dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(dbName), mysqlRepo.WithByMysqlName(name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -127,7 +127,7 @@ func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error {
|
||||
if !fileOp.Stat(req.File) {
|
||||
return errors.New(fmt.Sprintf("%s file is not exist", req.File))
|
||||
}
|
||||
dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(req.DetailName))
|
||||
dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(req.DetailName), mysqlRepo.WithByMysqlName(req.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -254,15 +255,18 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, backup model.Back
|
||||
return paths, err
|
||||
}
|
||||
|
||||
var dblist []string
|
||||
var dbs []model.DatabaseMysql
|
||||
if cronjob.DBName == "all" {
|
||||
mysqlService := NewIMysqlService()
|
||||
dblist, err = mysqlService.ListDBName()
|
||||
dbs, err = mysqlRepo.List()
|
||||
if err != nil {
|
||||
return paths, err
|
||||
}
|
||||
} else {
|
||||
dblist = append(dblist, cronjob.DBName)
|
||||
itemID, _ := (strconv.Atoi(cronjob.DBName))
|
||||
dbs, err = mysqlRepo.List(commonRepo.WithByID(uint(itemID)))
|
||||
if err != nil {
|
||||
return paths, err
|
||||
}
|
||||
}
|
||||
|
||||
var client cloud_storage.CloudStorageClient
|
||||
@ -273,25 +277,21 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, backup model.Back
|
||||
}
|
||||
}
|
||||
|
||||
for _, dbName := range dblist {
|
||||
for _, dbInfo := range dbs {
|
||||
var record model.BackupRecord
|
||||
|
||||
record.Type = "mysql"
|
||||
record.Source = "LOCAL"
|
||||
record.BackupType = backup.Type
|
||||
|
||||
dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(dbName))
|
||||
if err != nil {
|
||||
return paths, err
|
||||
}
|
||||
record.Name = dbInfo.MysqlName
|
||||
backupDir := path.Join(localDir, fmt.Sprintf("database/mysql/%s/%s", record.Name, dbName))
|
||||
record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbName, startTime.Format("20060102150405"))
|
||||
if err = handleMysqlBackup(dbName, backupDir, record.FileName); err != nil {
|
||||
backupDir := path.Join(localDir, fmt.Sprintf("database/mysql/%s/%s", record.Name, dbInfo.Name))
|
||||
record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format("20060102150405"))
|
||||
if err = handleMysqlBackup(dbInfo.MysqlName, dbInfo.Name, backupDir, record.FileName); err != nil {
|
||||
return paths, err
|
||||
}
|
||||
|
||||
record.DetailName = dbName
|
||||
record.DetailName = dbInfo.Name
|
||||
record.FileDir = backupDir
|
||||
itemFileDir := strings.TrimPrefix(backupDir, localDir+"/")
|
||||
if !cronjob.KeepLocal && backup.Type != "LOCAL" {
|
||||
|
@ -32,7 +32,7 @@ type MysqlService struct{}
|
||||
|
||||
type IMysqlService interface {
|
||||
SearchWithPage(search dto.MysqlDBSearch) (int64, interface{}, error)
|
||||
ListDBName() ([]string, error)
|
||||
ListDBOption() ([]dto.MysqlOption, error)
|
||||
Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error)
|
||||
LoadFromRemote(from string) error
|
||||
ChangeAccess(info dto.ChangeDBInfo) error
|
||||
@ -71,13 +71,17 @@ func (u *MysqlService) SearchWithPage(search dto.MysqlDBSearch) (int64, interfac
|
||||
return total, dtoMysqls, err
|
||||
}
|
||||
|
||||
func (u *MysqlService) ListDBName() ([]string, error) {
|
||||
func (u *MysqlService) ListDBOption() ([]dto.MysqlOption, error) {
|
||||
mysqls, err := mysqlRepo.List()
|
||||
var dbNames []string
|
||||
var dbs []dto.MysqlOption
|
||||
for _, mysql := range mysqls {
|
||||
dbNames = append(dbNames, mysql.Name)
|
||||
var item dto.MysqlOption
|
||||
if err := copier.Copy(&item, &mysql); err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
dbs = append(dbs, item)
|
||||
}
|
||||
return dbNames, err
|
||||
return dbs, err
|
||||
}
|
||||
|
||||
func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error) {
|
||||
@ -85,6 +89,11 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
|
||||
return nil, buserr.New(constant.ErrCmdIllegal)
|
||||
}
|
||||
|
||||
mysql, _ := mysqlRepo.Get(commonRepo.WithByName(req.Name), remoteDBRepo.WithByFrom(req.From))
|
||||
if mysql.ID != 0 {
|
||||
return nil, constant.ErrRecordExist
|
||||
}
|
||||
|
||||
var createItem model.DatabaseMysql
|
||||
if err := copier.Copy(&createItem, &req); err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
|
@ -60,6 +60,9 @@ func (r *Local) CreateUser(info CreateInfo) error {
|
||||
|
||||
for _, user := range userlist {
|
||||
if err := r.ExecSQL(fmt.Sprintf("create user %s identified by '%s';", user, info.Password), info.Timeout); err != nil {
|
||||
if strings.Contains(err.Error(), "ERROR 1396") {
|
||||
return buserr.New(constant.ErrUserIsExist)
|
||||
}
|
||||
_ = r.Delete(DeleteInfo{
|
||||
Name: info.Name,
|
||||
Version: info.Version,
|
||||
@ -67,9 +70,6 @@ func (r *Local) CreateUser(info CreateInfo) error {
|
||||
Permission: info.Permission,
|
||||
ForceDelete: true,
|
||||
Timeout: 300})
|
||||
if strings.Contains(err.Error(), "ERROR 1396") {
|
||||
return buserr.New(constant.ErrUserIsExist)
|
||||
}
|
||||
return err
|
||||
}
|
||||
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to %s", info.Name, user)
|
||||
|
@ -242,6 +242,10 @@ func (r *Remote) Recover(info RecoverInfo) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("gunzip file %s failed, stdout: %v, err: %v", info.SourceFile, string(stdout), err)
|
||||
}
|
||||
defer func() {
|
||||
gzipCmd := exec.Command("gzip", fileName)
|
||||
_, _ = gzipCmd.CombinedOutput()
|
||||
}()
|
||||
}
|
||||
dns := fmt.Sprintf("%s:%s@tcp(%s:%v)/%s?charset=%s&parseTime=true&loc=Asia%sShanghai", r.User, r.Password, r.Address, r.Port, info.Name, info.Format, "%2F")
|
||||
f, err := os.Open(fileName)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Package docs GENERATED BY SWAG; DO NOT EDIT
|
||||
// This file was generated by swaggo/swag
|
||||
// Code generated by swaggo/swag. DO NOT EDIT.
|
||||
|
||||
package docs
|
||||
|
||||
import "github.com/swaggo/swag"
|
||||
@ -4056,7 +4056,7 @@ const docTemplate = `{
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/dto.MysqlOption"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13147,6 +13147,20 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.MysqlOption": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.MysqlStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -4049,7 +4049,7 @@
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/dto.MysqlOption"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13140,6 +13140,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.MysqlOption": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.MysqlStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -1149,6 +1149,15 @@ definitions:
|
||||
- page
|
||||
- pageSize
|
||||
type: object
|
||||
dto.MysqlOption:
|
||||
properties:
|
||||
from:
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
dto.MysqlStatus:
|
||||
properties:
|
||||
Aborted_clients:
|
||||
@ -6414,7 +6423,7 @@ paths:
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
type: string
|
||||
$ref: '#/definitions/dto.MysqlOption'
|
||||
type: array
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
|
@ -111,6 +111,11 @@ export namespace Database {
|
||||
File: string;
|
||||
Position: number;
|
||||
}
|
||||
export interface MysqlOption {
|
||||
id: number;
|
||||
name: string;
|
||||
from: string;
|
||||
}
|
||||
export interface ChangeInfo {
|
||||
id: number;
|
||||
value: string;
|
||||
|
@ -59,8 +59,8 @@ export const loadMysqlStatus = () => {
|
||||
export const loadRemoteAccess = () => {
|
||||
return http.get<boolean>(`/databases/remote`);
|
||||
};
|
||||
export const loadDBNames = () => {
|
||||
return http.get<Array<string>>(`/databases/options`);
|
||||
export const loadDBOptions = () => {
|
||||
return http.get<Array<Database.MysqlOption>>(`/databases/options`);
|
||||
};
|
||||
|
||||
// redis
|
||||
|
@ -122,7 +122,18 @@
|
||||
<el-form-item :label="$t('cronjob.database')" prop="dbName">
|
||||
<el-select class="selectClass" clearable v-model="dialogData.rowData!.dbName">
|
||||
<el-option :label="$t('commons.table.all')" value="all" />
|
||||
<el-option v-for="item in mysqlInfo.dbNames" :key="item" :label="item" :value="item" />
|
||||
<div v-for="item in mysqlInfo.dbs" :key="item.id">
|
||||
<el-option
|
||||
v-if="item.from === 'local'"
|
||||
:label="$t('database.localDB') + ' [' + item.name + ']'"
|
||||
:value="item.id + ''"
|
||||
/>
|
||||
<el-option
|
||||
v-else
|
||||
:label="item.from + ' [' + item.name + ']'"
|
||||
:value="item.id + ''"
|
||||
/>
|
||||
</div>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
@ -219,12 +230,13 @@ import i18n from '@/lang';
|
||||
import { ElForm } from 'element-plus';
|
||||
import { Cronjob } from '@/api/interface/cronjob';
|
||||
import { addCronjob, editCronjob } from '@/api/modules/cronjob';
|
||||
import { loadDBNames } from '@/api/modules/database';
|
||||
import { loadDBOptions } from '@/api/modules/database';
|
||||
import { GetWebsiteOptions } from '@/api/modules/website';
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { listContainer } from '@/api/modules/container';
|
||||
import { Database } from '@/api/interface/database';
|
||||
const router = useRouter();
|
||||
|
||||
interface DialogProps {
|
||||
@ -275,7 +287,7 @@ const mysqlInfo = reactive({
|
||||
isExist: false,
|
||||
name: '',
|
||||
version: '',
|
||||
dbNames: [] as Array<string>,
|
||||
dbs: [] as Array<Database.MysqlOption>,
|
||||
});
|
||||
|
||||
const varifySpec = (rule: any, value: any, callback: any) => {
|
||||
@ -458,8 +470,8 @@ const loadContainers = async () => {
|
||||
};
|
||||
|
||||
const checkMysqlInstalled = async () => {
|
||||
const data = await loadDBNames();
|
||||
mysqlInfo.dbNames = data.data || [];
|
||||
const data = await loadDBOptions();
|
||||
mysqlInfo.dbs = data.data || [];
|
||||
};
|
||||
|
||||
function isBackup() {
|
||||
|
@ -190,6 +190,7 @@ const onSave = async (formEl: FormInstance | undefined) => {
|
||||
const onSubmitAccess = async () => {
|
||||
let param = {
|
||||
id: 0,
|
||||
from: form.from,
|
||||
value: form.privilege ? '%' : 'localhost',
|
||||
};
|
||||
loading.value = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user