diff --git a/backend/app/api/v1/database_mysql.go b/backend/app/api/v1/database_mysql.go index 05278000c..7db1aeda2 100644 --- a/backend/app/api/v1/database_mysql.go +++ b/backend/app/api/v1/database_mysql.go @@ -81,13 +81,13 @@ func (b *BaseApi) SearchMysql(c *gin.Context) { } func (b *BaseApi) ListDBNameByVersion(c *gin.Context) { - version, ok := c.Params.Get("version") + name, ok := c.Params.Get("name") if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error version in path")) + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path")) return } - list, err := mysqlService.ListDBByVersion(version) + list, err := mysqlService.ListDBByVersion(name) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -155,13 +155,13 @@ func (b *BaseApi) DeleteMysql(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - version, ok := c.Params.Get("version") + name, ok := c.Params.Get("name") if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error version in path")) + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path")) return } - if err := mysqlService.Delete(version, req.Ids); err != nil { + if err := mysqlService.Delete(name, req.Ids); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } @@ -179,13 +179,13 @@ func (b *BaseApi) LoadVersions(c *gin.Context) { } func (b *BaseApi) LoadBaseinfo(c *gin.Context) { - version, ok := c.Params.Get("version") + name, ok := c.Params.Get("name") if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error version in path")) + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path")) return } - data, err := mysqlService.LoadBaseInfo(version) + data, err := mysqlService.LoadBaseInfo(name) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -195,13 +195,13 @@ func (b *BaseApi) LoadBaseinfo(c *gin.Context) { } func (b *BaseApi) LoadStatus(c *gin.Context) { - version, ok := c.Params.Get("version") + name, ok := c.Params.Get("name") if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error version in path")) + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path")) return } - data, err := mysqlService.LoadStatus(version) + data, err := mysqlService.LoadStatus(name) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -211,12 +211,12 @@ func (b *BaseApi) LoadStatus(c *gin.Context) { } func (b *BaseApi) LoadVariables(c *gin.Context) { - version, ok := c.Params.Get("version") + name, ok := c.Params.Get("name") if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error version in path")) + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path")) return } - data, err := mysqlService.LoadVariables(version) + data, err := mysqlService.LoadVariables(name) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/api/v1/database_redis.go b/backend/app/api/v1/database_redis.go index 255c4a55a..86dce5fe5 100644 --- a/backend/app/api/v1/database_redis.go +++ b/backend/app/api/v1/database_redis.go @@ -1,9 +1,6 @@ package v1 import ( - "errors" - "strconv" - "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" @@ -65,19 +62,84 @@ func (b *BaseApi) DeleteRedis(c *gin.Context) { helper.SuccessWithData(c, nil) } -func (b *BaseApi) CleanRedis(c *gin.Context) { - db, ok := c.Params.Get("db") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error db in path")) +func (b *BaseApi) LoadRedisRunningVersion(c *gin.Context) { + list, err := redisService.LoadRedisRunningVersion() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - dbNum, err := strconv.Atoi(db) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error db in path")) + helper.SuccessWithData(c, list) +} + +func (b *BaseApi) LoadRedisStatus(c *gin.Context) { + var req dto.RedisBaseReq + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - if err := redisService.CleanAll(dbNum); err != nil { + data, err := redisService.LoadState(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, data) +} + +func (b *BaseApi) LoadRedisConf(c *gin.Context) { + var req dto.RedisBaseReq + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + data, err := redisService.LoadConf(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, data) +} + +func (b *BaseApi) CleanRedis(c *gin.Context) { + var req dto.RedisBaseReq + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + if err := redisService.CleanAll(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +func (b *BaseApi) UpdateRedisConf(c *gin.Context) { + var req dto.RedisConfUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := redisService.UpdateConf(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } diff --git a/backend/app/dto/database.go b/backend/app/dto/database.go index e28f15d01..61c41c575 100644 --- a/backend/app/dto/database.go +++ b/backend/app/dto/database.go @@ -16,7 +16,7 @@ type MysqlDBInfo struct { type MysqlDBCreate struct { Name string `json:"name" validate:"required"` - Version string `json:"version" validate:"required,oneof=mysql5.7 mysql8.0"` + MysqlName string `json:"mysqlName" validate:"required"` Format string `json:"format" validate:"required,oneof=utf8mb4 utf-8 gbk big5"` Username string `json:"username" validate:"required"` Password string `json:"password" validate:"required"` @@ -82,7 +82,7 @@ type MysqlVariables struct { } type MysqlVariablesUpdate struct { - Version string `json:"version" validate:"required,oneof=mysql5.7 mysql8.0"` + MysqlName string `json:"mysqlName" validate:"required"` KeyBufferSize int64 `json:"key_buffer_size" validate:"required"` QueryCacheSize int64 `json:"query_cache_size" validate:"required"` TmpTableSize int64 `json:"tmp_table_size" validate:"required"` @@ -102,7 +102,7 @@ type MysqlVariablesUpdate struct { type ChangeDBInfo struct { ID uint `json:"id"` - Version string `json:"version" validate:"required,oneof=mysql5.7 mysql8.0"` + MysqlName string `json:"mysqlName" validate:"required"` Operation string `json:"operation" validate:"required,oneof=password privilege"` Value string `json:"value" validate:"required"` } @@ -112,26 +112,27 @@ type DBBaseInfo struct { Port int64 `json:"port"` Password string `json:"password"` RemoteConn bool `json:"remoteConn"` + MysqlKey string `json:"mysqlKey"` } type SearchDBWithPage struct { PageInfo - Version string `json:"version" validate:"required,oneof=mysql5.7 mysql8.0"` + MysqlName string `json:"mysqlName" validate:"required"` } type SearchBackupsWithPage struct { PageInfo - Version string `json:"version" validate:"required,oneof=mysql5.7 mysql8.0"` - DBName string `json:"dbName" validate:"required"` + MysqlName string `json:"mysqlName" validate:"required"` + DBName string `json:"dbName" validate:"required"` } type BackupDB struct { - Version string `json:"version" validate:"required,oneof=mysql5.7 mysql8.0"` - DBName string `json:"dbName" validate:"required"` + MysqlName string `json:"mysqlName" validate:"required"` + DBName string `json:"dbName" validate:"required"` } type RecoverDB struct { - Version string `json:"version" validate:"required,oneof=mysql5.7 mysql8.0"` + MysqlName string `json:"mysqlName" validate:"required"` DBName string `json:"dbName" validate:"required"` BackupName string `json:"backupName" validate:"required"` } @@ -139,7 +140,8 @@ type RecoverDB struct { // redis type SearchRedisWithPage struct { PageInfo - DB int `json:"db" validate:"required"` + RedisName string `json:"redisName" validate:"required"` + DB int `json:"db" validate:"required"` } type RedisData struct { @@ -151,6 +153,7 @@ type RedisData struct { } type RedisDataSet struct { + RedisName string `json:"redisName" validate:"required"` DB int `json:"db"` Key string `json:"key" validate:"required"` Value string `json:"value" validate:"required"` @@ -158,6 +161,48 @@ type RedisDataSet struct { } type RedisDelBatch struct { - DB int `json:"db" validate:"required"` - Names []string `json:"names" validate:"required"` + RedisName string `json:"redisName" validate:"required"` + DB int `json:"db" validate:"required"` + Names []string `json:"names" validate:"required"` +} + +type RedisBaseReq struct { + RedisName string `json:"redisName" validate:"required"` + DB int `json:"db"` +} + +type RedisConfUpdate struct { + RedisName string `json:"redisName" validate:"required"` + DB int `json:"db"` + ParamName string `json:"paramName" validate:"required"` + Value string `json:"value"` +} + +type RedisConf struct { + Timeout string `json:"timeout"` + Maxclients string `json:"maxclients"` + Databases string `json:"databases"` + Requirepass string `json:"requirepass"` + Maxmemory string `json:"maxmemory"` + + Dir string `json:"dir"` + Appendonly string `json:"appendonly"` + Appendfsync string `json:"appendfsync"` + Save string `json:"save"` +} + +type RedisStatus struct { + TcpPort string `json:"tcp_port"` + UptimeInDays string `json:"uptime_in_days"` + ConnectedClients string `json:"connected_clients"` + UsedMemory string `json:"used_memory"` + UsedMemory_rss string `json:"used_memory_rss"` + UsedMemory_peak string `json:"used_memory_peak"` + MemFragmentationRatio string `json:"mem_fragmentation_ratio"` + TotalConnectionsReceived string `json:"total_connections_received"` + TotalCommandsProcessed string `json:"total_commands_processed"` + InstantaneousOpsPerSec string `json:"instantaneous_ops_per_sec"` + KeyspaceHits string `json:"keyspace_hits"` + KeyspaceMisses string `json:"keyspace_misses"` + LatestForkUsec string `json:"latest_fork_usec"` } diff --git a/backend/app/model/database_mysql.go b/backend/app/model/database_mysql.go index 998cf6ad4..bc699aac4 100644 --- a/backend/app/model/database_mysql.go +++ b/backend/app/model/database_mysql.go @@ -3,7 +3,7 @@ package model type DatabaseMysql struct { BaseModel Name string `json:"name" gorm:"type:varchar(256);not null"` - Version string `json:"version" gorm:"type:varchar(64);not null"` + MysqlName string `json:"mysqlName" gorm:"type:varchar(64);not null"` Format string `json:"format" gorm:"type:varchar(64);not null"` Username string `json:"username" gorm:"type:varchar(256);not null"` Password string `json:"password" gorm:"type:varchar(256);not null"` diff --git a/backend/app/repo/databse_mysql.go b/backend/app/repo/databse_mysql.go index 51db39042..56ab36c2d 100644 --- a/backend/app/repo/databse_mysql.go +++ b/backend/app/repo/databse_mysql.go @@ -13,14 +13,15 @@ type MysqlRepo struct{} type IMysqlRepo interface { Get(opts ...DBOption) (model.DatabaseMysql, error) - WithByVersion(version string) DBOption + WithByMysqlName(mysqlName string) DBOption List(opts ...DBOption) ([]model.DatabaseMysql, error) Page(limit, offset int, opts ...DBOption) (int64, []model.DatabaseMysql, error) Create(mysql *model.DatabaseMysql) error Delete(opts ...DBOption) error Update(id uint, vars map[string]interface{}) error - LoadRunningVersion() ([]string, error) - LoadBaseInfoByKey(key string) (*RootInfo, error) + LoadRunningVersion(keys []string) ([]string, error) + LoadBaseInfoByName(name string) (*RootInfo, error) + LoadRedisBaseInfoByName(name string) (*RootInfo, error) UpdateMysqlConf(id uint, vars map[string]interface{}) error } @@ -60,21 +61,21 @@ func (u *MysqlRepo) Page(page, size int, opts ...DBOption) (int64, []model.Datab return count, users, err } -func (u *MysqlRepo) LoadRunningVersion() ([]string, error) { +func (u *MysqlRepo) LoadRunningVersion(keys []string) ([]string, error) { var ( apps []model.App - appInstall model.AppInstall + appInstall []model.AppInstall results []string ) - if err := global.DB.Where("name = ? OR name = ?", "Mysql5.7", "Mysql8.0").Find(&apps).Error; err != nil { + if err := global.DB.Where("name in (?)", keys).Find(&apps).Error; err != nil { return nil, err } for _, app := range apps { - if err := global.DB.Where("app_id = ?", app.ID).First(&appInstall).Error; err != nil && err != gorm.ErrRecordNotFound { + if err := global.DB.Where("app_id = ?", app.ID).Find(&appInstall).Error; err != nil { return nil, err } - if appInstall.ID != 0 { - results = append(results, app.Key) + for _, item := range appInstall { + results = append(results, item.Name) } } return results, nil @@ -88,18 +89,56 @@ type RootInfo struct { ContainerName string `json:"containerName"` Param string `json:"param"` Env string `json:"env"` + Key string `json:"key"` } -func (u *MysqlRepo) LoadBaseInfoByKey(key string) (*RootInfo, error) { +func (u *MysqlRepo) LoadBaseInfoByName(name string) (*RootInfo, error) { var ( app model.App appInstall model.AppInstall info RootInfo ) - if err := global.DB.Where("key = ?", key).First(&app).Error; err != nil { + if err := global.DB.Where("name = ?", name).First(&appInstall).Error; err != nil { return nil, err } - if err := global.DB.Where("app_id = ?", app.ID).First(&appInstall).Error; err != nil { + if err := global.DB.Where("id = ?", appInstall.AppId).First(&app).Error; err != nil { + return nil, err + } + envMap := make(map[string]interface{}) + if err := json.Unmarshal([]byte(appInstall.Env), &envMap); err != nil { + return nil, err + } + password, ok := envMap["PANEL_DB_ROOT_PASSWORD"].(string) + if ok { + info.Password = password + } else { + return nil, errors.New("error password in db") + } + port, ok := envMap["PANEL_APP_PORT_HTTP"].(float64) + if ok { + info.Port = int64(port) + } else { + return nil, errors.New("error port in db") + } + info.ID = appInstall.ID + info.Key = app.Key + info.ContainerName = appInstall.ContainerName + info.Name = appInstall.Name + info.Env = appInstall.Env + info.Param = appInstall.Param + return &info, nil +} + +func (u *MysqlRepo) LoadRedisBaseInfoByName(name string) (*RootInfo, error) { + var ( + app model.App + appInstall model.AppInstall + info RootInfo + ) + if err := global.DB.Where("key = ?", "redis").First(&app).Error; err != nil { + return nil, err + } + if err := global.DB.Where("app_id = ? AND name = ?", app.ID, name).First(&appInstall).Error; err != nil { return nil, err } envMap := make(map[string]interface{}) @@ -149,8 +188,8 @@ func (u *MysqlRepo) UpdateMysqlConf(id uint, vars map[string]interface{}) error return nil } -func (c *MysqlRepo) WithByVersion(version string) DBOption { +func (c *MysqlRepo) WithByMysqlName(mysqlName string) DBOption { return func(g *gorm.DB) *gorm.DB { - return g.Where("version = ?", version) + return g.Where("mysql_name = ?", mysqlName) } } diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go index 00be98f11..4a5a3ab78 100644 --- a/backend/app/service/database_mysql.go +++ b/backend/app/service/database_mysql.go @@ -23,7 +23,7 @@ type MysqlService struct{} type IMysqlService interface { SearchWithPage(search dto.SearchDBWithPage) (int64, interface{}, error) - ListDBByVersion(version string) ([]string, error) + ListDBByVersion(name string) ([]string, error) SearchBackupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error) Create(mysqlDto dto.MysqlDBCreate) error ChangeInfo(info dto.ChangeDBInfo) error @@ -32,11 +32,11 @@ type IMysqlService interface { Backup(db dto.BackupDB) error Recover(db dto.RecoverDB) error - Delete(version string, ids []uint) error - LoadStatus(version string) (*dto.MysqlStatus, error) - LoadVariables(version string) (*dto.MysqlVariables, error) + Delete(name string, ids []uint) error + LoadStatus(name string) (*dto.MysqlStatus, error) + LoadVariables(vernamesion string) (*dto.MysqlVariables, error) LoadRunningVersion() ([]string, error) - LoadBaseInfo(version string) (*dto.DBBaseInfo, error) + LoadBaseInfo(name string) (*dto.DBBaseInfo, error) } func NewIMysqlService() IMysqlService { @@ -44,7 +44,7 @@ func NewIMysqlService() IMysqlService { } func (u *MysqlService) SearchWithPage(search dto.SearchDBWithPage) (int64, interface{}, error) { - total, mysqls, err := mysqlRepo.Page(search.Page, search.PageSize, mysqlRepo.WithByVersion(search.Version)) + total, mysqls, err := mysqlRepo.Page(search.Page, search.PageSize, mysqlRepo.WithByMysqlName(search.MysqlName)) var dtoMysqls []dto.MysqlDBInfo for _, mysql := range mysqls { var item dto.MysqlDBInfo @@ -56,8 +56,8 @@ func (u *MysqlService) SearchWithPage(search dto.SearchDBWithPage) (int64, inter return total, dtoMysqls, err } -func (u *MysqlService) ListDBByVersion(version string) ([]string, error) { - mysqls, err := mysqlRepo.List(mysqlRepo.WithByVersion(version)) +func (u *MysqlService) ListDBByVersion(name string) ([]string, error) { + mysqls, err := mysqlRepo.List(commonRepo.WithByName(name)) var dbNames []string for _, mysql := range mysqls { dbNames = append(dbNames, mysql.Name) @@ -66,7 +66,7 @@ func (u *MysqlService) ListDBByVersion(version string) ([]string, error) { } func (u *MysqlService) SearchBackupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error) { - app, err := mysqlRepo.LoadBaseInfoByKey(search.Version) + app, err := mysqlRepo.LoadBaseInfoByName(search.MysqlName) if err != nil { return 0, nil, err } @@ -81,7 +81,7 @@ func (u *MysqlService) SearchBackupsWithPage(search dto.SearchBackupsWithPage) ( } func (u *MysqlService) LoadRunningVersion() ([]string, error) { - return mysqlRepo.LoadRunningVersion() + return mysqlRepo.LoadRunningVersion([]string{"Mysql5.7", "Mysql8.0"}) } func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error { @@ -96,7 +96,7 @@ func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error { return errors.WithMessage(constant.ErrStructTransform, err.Error()) } - app, err := mysqlRepo.LoadBaseInfoByKey(mysqlDto.Version) + app, err := mysqlRepo.LoadBaseInfoByName(mysqlDto.MysqlName) if err != nil { return err } @@ -108,7 +108,7 @@ func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error { return err } grantStr := fmt.Sprintf("grant all privileges on %s.* to '%s'@'%s'", mysqlDto.Name, mysqlDto.Username, tmpPermission) - if mysqlDto.Version == "5.7.39" { + if app.Key == "mysql5.7" { grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysqlDto.Password) } if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil { @@ -129,16 +129,16 @@ func (u *MysqlService) Backup(db dto.BackupDB) error { if err != nil { return err } - backupDir := fmt.Sprintf("database/%s/%s", db.Version, db.DBName) + backupDir := fmt.Sprintf("database/%s/%s", db.MysqlName, db.DBName) fileName := fmt.Sprintf("%s_%s.sql.gz", db.DBName, time.Now().Format("20060102150405")) - if err := backupMysql("LOCAL", localDir, backupDir, db.Version, db.DBName, fileName); err != nil { + if err := backupMysql("LOCAL", localDir, backupDir, db.MysqlName, db.DBName, fileName); err != nil { return err } return nil } func (u *MysqlService) Recover(db dto.RecoverDB) error { - app, err := mysqlRepo.LoadBaseInfoByKey(db.Version) + app, err := mysqlRepo.LoadBaseInfoByName(db.MysqlName) if err != nil { return err } @@ -162,8 +162,8 @@ func (u *MysqlService) Recover(db dto.RecoverDB) error { return nil } -func (u *MysqlService) Delete(version string, ids []uint) error { - app, err := mysqlRepo.LoadBaseInfoByKey(version) +func (u *MysqlService) Delete(name string, ids []uint) error { + app, err := mysqlRepo.LoadBaseInfoByName(name) if err != nil { return err } @@ -198,7 +198,7 @@ func (u *MysqlService) ChangeInfo(info dto.ChangeDBInfo) error { return err } } - app, err := mysqlRepo.LoadBaseInfoByKey(info.Version) + app, err := mysqlRepo.LoadBaseInfoByName(info.MysqlName) if err != nil { return err } @@ -247,7 +247,7 @@ func (u *MysqlService) ChangeInfo(info dto.ChangeDBInfo) error { return err } grantStr := fmt.Sprintf("grant all privileges on %s.* to '%s'@'%s'", mysql.Name, mysql.Username, info.Value) - if mysql.Version == "5.7.39" { + if app.Key == "mysql5.7" { grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysql.Password) } if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil { @@ -266,7 +266,7 @@ func (u *MysqlService) ChangeInfo(info dto.ChangeDBInfo) error { } func (u *MysqlService) UpdateVariables(variables dto.MysqlVariablesUpdate) error { - app, err := mysqlRepo.LoadBaseInfoByKey(variables.Version) + app, err := mysqlRepo.LoadBaseInfoByName(variables.MysqlName) if err != nil { return err } @@ -318,15 +318,16 @@ func (u *MysqlService) UpdateVariables(variables dto.MysqlVariablesUpdate) error return nil } -func (u *MysqlService) LoadBaseInfo(version string) (*dto.DBBaseInfo, error) { +func (u *MysqlService) LoadBaseInfo(name string) (*dto.DBBaseInfo, error) { var data dto.DBBaseInfo - app, err := mysqlRepo.LoadBaseInfoByKey(version) + app, err := mysqlRepo.LoadBaseInfoByName(name) if err != nil { return nil, err } data.Name = app.Name data.Port = int64(app.Port) data.Password = app.Password + data.MysqlKey = app.Key hosts, err := excuteSqlForRows(app.ContainerName, app.Password, "select host from mysql.user where user='root';") if err != nil { @@ -341,8 +342,8 @@ func (u *MysqlService) LoadBaseInfo(version string) (*dto.DBBaseInfo, error) { return &data, nil } -func (u *MysqlService) LoadVariables(version string) (*dto.MysqlVariables, error) { - app, err := mysqlRepo.LoadBaseInfoByKey(version) +func (u *MysqlService) LoadVariables(name string) (*dto.MysqlVariables, error) { + app, err := mysqlRepo.LoadBaseInfoByName(name) if err != nil { return nil, err } @@ -359,8 +360,8 @@ func (u *MysqlService) LoadVariables(version string) (*dto.MysqlVariables, error return &info, nil } -func (u *MysqlService) LoadStatus(version string) (*dto.MysqlStatus, error) { - app, err := mysqlRepo.LoadBaseInfoByKey(version) +func (u *MysqlService) LoadStatus(name string) (*dto.MysqlStatus, error) { + app, err := mysqlRepo.LoadBaseInfoByName(name) if err != nil { return nil, err } @@ -443,8 +444,8 @@ func excuteSql(containerName, password, command string) error { return nil } -func backupMysql(backupType, baseDir, backupDir, version, dbName, fileName string) error { - app, err := mysqlRepo.LoadBaseInfoByKey(version) +func backupMysql(backupType, baseDir, backupDir, mysqkName, dbName, fileName string) error { + app, err := mysqlRepo.LoadBaseInfoByName(mysqkName) if err != nil { return err } diff --git a/backend/app/service/database_redis.go b/backend/app/service/database_redis.go index 3b562bd0a..278ca4420 100644 --- a/backend/app/service/database_redis.go +++ b/backend/app/service/database_redis.go @@ -1,7 +1,9 @@ package service import ( + "encoding/json" "fmt" + "strings" "time" "github.com/1Panel-dev/1Panel/backend/app/dto" @@ -15,7 +17,13 @@ type IRedisService interface { SearchWithPage(search dto.SearchRedisWithPage) (int64, interface{}, error) Set(setData dto.RedisDataSet) error Delete(info dto.RedisDelBatch) error - CleanAll(db int) error + + UpdateConf(req dto.RedisConfUpdate) error + + CleanAll(req dto.RedisBaseReq) error + LoadState(req dto.RedisBaseReq) (*dto.RedisStatus, error) + LoadConf(req dto.RedisBaseReq) (*dto.RedisConf, error) + LoadRedisRunningVersion() ([]string, error) // Backup(db dto.BackupDB) error // Recover(db dto.RecoverDB) error @@ -25,16 +33,24 @@ func NewIRedisService() IRedisService { return &RedisService{} } -func (u *RedisService) SearchWithPage(search dto.SearchRedisWithPage) (int64, interface{}, error) { - redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis") +func newRedisClient(name string, db int) (*redis.Client, error) { + redisInfo, err := mysqlRepo.LoadRedisBaseInfoByName(name) if err != nil { - return 0, nil, err + return nil, err } client := redis.NewClient(&redis.Options{ Addr: fmt.Sprintf("localhost:%v", redisInfo.Port), Password: "eYVX7EwVmmxKPCDmwMtyKVge8oLd2t81", - DB: search.DB, + DB: db, }) + return client, nil +} + +func (u *RedisService) SearchWithPage(search dto.SearchRedisWithPage) (int64, interface{}, error) { + client, err := newRedisClient(search.RedisName, search.DB) + if err != nil { + return 0, nil, err + } total, err := client.DbSize().Result() if err != nil { return 0, nil, err @@ -72,16 +88,30 @@ func (u *RedisService) SearchWithPage(search dto.SearchRedisWithPage) (int64, in return total, data, nil } -func (u *RedisService) Set(setData dto.RedisDataSet) error { - redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis") +func (u *RedisService) LoadRedisRunningVersion() ([]string, error) { + return mysqlRepo.LoadRunningVersion([]string{"redis"}) +} + +func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error { + client, err := newRedisClient(req.RedisName, 0) + if err != nil { + return err + } + if _, err := client.ConfigSet(req.ParamName, req.Value).Result(); err != nil { + return err + } + if _, err := client.ConfigRewrite().Result(); err != nil { + return err + } + + return nil +} + +func (u *RedisService) Set(setData dto.RedisDataSet) error { + client, err := newRedisClient(setData.RedisName, setData.DB) if err != nil { return err } - client := redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("localhost:%v", redisInfo.Port), - Password: "eYVX7EwVmmxKPCDmwMtyKVge8oLd2t81", - DB: setData.DB, - }) value, _ := client.Get(setData.Key).Result() if err != nil { return err @@ -98,33 +128,78 @@ func (u *RedisService) Set(setData dto.RedisDataSet) error { } func (u *RedisService) Delete(req dto.RedisDelBatch) error { - redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis") + client, err := newRedisClient(req.RedisName, req.DB) if err != nil { return err } - client := redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("localhost:%v", redisInfo.Port), - Password: "eYVX7EwVmmxKPCDmwMtyKVge8oLd2t81", - DB: req.DB, - }) if _, err := client.Del(req.Names...).Result(); err != nil { return err } return nil } -func (u *RedisService) CleanAll(db int) error { - redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis") +func (u *RedisService) CleanAll(req dto.RedisBaseReq) error { + client, err := newRedisClient(req.RedisName, req.DB) if err != nil { return err } - client := redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("localhost:%v", redisInfo.Port), - Password: "eYVX7EwVmmxKPCDmwMtyKVge8oLd2t81", - DB: db, - }) if _, err := client.FlushAll().Result(); err != nil { return err } return nil } + +func (u *RedisService) LoadState(req dto.RedisBaseReq) (*dto.RedisStatus, error) { + client, err := newRedisClient(req.RedisName, req.DB) + if err != nil { + return nil, err + } + stdStr, err := client.Info().Result() + if err != nil { + return nil, err + } + rows := strings.Split(stdStr, "\r\n") + rowMap := make(map[string]string) + for _, v := range rows { + itemRow := strings.Split(v, ":") + if len(itemRow) == 2 { + rowMap[itemRow[0]] = itemRow[1] + } + } + var info dto.RedisStatus + arr, err := json.Marshal(rowMap) + if err != nil { + return nil, err + } + _ = json.Unmarshal(arr, &info) + return &info, nil +} + +func (u *RedisService) LoadConf(req dto.RedisBaseReq) (*dto.RedisConf, error) { + client, err := newRedisClient(req.RedisName, req.DB) + if err != nil { + return nil, err + } + var item dto.RedisConf + item.Timeout = configGetStr(client, "timeout") + item.Maxclients = configGetStr(client, "maxclients") + item.Databases = configGetStr(client, "databases") + item.Requirepass = configGetStr(client, "requirepass") + item.Maxmemory = configGetStr(client, "maxmemory") + + item.Dir = configGetStr(client, "dir") + item.Appendonly = configGetStr(client, "appendonly") + item.Appendfsync = configGetStr(client, "appendfsync") + item.Save = configGetStr(client, "save") + return &item, nil +} + +func configGetStr(client *redis.Client, param string) string { + item, _ := client.ConfigGet(param).Result() + if len(item) == 2 { + if value, ok := item[1].(string); ok { + return value + } + } + return "" +} diff --git a/backend/app/service/database_test.go b/backend/app/service/database_test.go index 0dabb461d..d56e5b356 100644 --- a/backend/app/service/database_test.go +++ b/backend/app/service/database_test.go @@ -3,7 +3,6 @@ package service import ( "fmt" "testing" - "time" "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/go-redis/redis" @@ -15,48 +14,31 @@ func TestMysql(t *testing.T) { Password: "eYVX7EwVmmxKPCDmwMtyKVge8oLd2t81", DB: 0, }) - // fmt.Println(rdb.Get("dqwas")) - client.Set("omg", "111", 10*time.Minute) - client.Set("omg1", "111", 10*time.Minute) - client.Set("omg2", "111", 10*time.Minute) - client.Set("omg3", "111", 10*time.Minute) - client.Set("omg4", "111", 10*time.Minute) - client.Set("omg5", "111", 10*time.Minute) - client.Set("omg6", "111", 10*time.Minute) - client.Set("omg7", "111", 10*time.Minute) - client.Set("omg8", "111", 10*time.Minute) - client.Set("omg9", "111", 10*time.Minute) - keys, _, err := client.Scan(0, "*", 5).Result() - if err != nil { - panic(err) + var item dto.RedisConf + dir, _ := client.ConfigGet("dir").Result() + if len(dir) == 2 { + if value, ok := dir[1].(string); ok { + item.Dir = value + } } - - var data []dto.RedisData - for _, key := range keys { - var dataItem dto.RedisData - dataItem.Key = key - value, err := client.Get(key).Result() - if err != nil { - fmt.Println(err) + appendonly, _ := client.ConfigGet("appendonly").Result() + if len(appendonly) == 2 { + if value, ok := appendonly[1].(string); ok { + item.Appendonly = value } - dataItem.Value = value - typeVal, err := client.Type(key).Result() - if err != nil { - fmt.Println(err) - } - dataItem.Type = typeVal - length, err := client.StrLen(key).Result() - if err != nil { - fmt.Println(err) - } - dataItem.Length = length - ttl, err := client.TTL(key).Result() - if err != nil { - fmt.Println(err) - } - dataItem.Expiration = int64(ttl / 1000000000) - data = append(data, dataItem) } - fmt.Println(data) + appendfsync, _ := client.ConfigGet("appendfsync").Result() + if len(appendfsync) == 2 { + if value, ok := appendfsync[1].(string); ok { + item.Appendfsync = value + } + } + save, _ := client.ConfigGet("save").Result() + if len(save) == 2 { + if value, ok := save[1].(string); ok { + item.Save = value + } + } + fmt.Println(item) } diff --git a/backend/router/ro_database.go b/backend/router/ro_database.go index 498f8cdb2..67f290357 100644 --- a/backend/router/ro_database.go +++ b/backend/router/ro_database.go @@ -29,15 +29,19 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { withRecordRouter.POST("/del", baseApi.DeleteMysql) withRecordRouter.POST("/variables/update", baseApi.UpdateMysqlVariables) cmdRouter.POST("/search", baseApi.SearchMysql) - cmdRouter.GET("/variables/:version", baseApi.LoadVariables) - cmdRouter.GET("/status/:version", baseApi.LoadStatus) - cmdRouter.GET("/baseinfo/:version", baseApi.LoadBaseinfo) + cmdRouter.GET("/variables/:name", baseApi.LoadVariables) + cmdRouter.GET("/status/:name", baseApi.LoadStatus) + cmdRouter.GET("/baseinfo/:name", baseApi.LoadBaseinfo) cmdRouter.GET("/versions", baseApi.LoadVersions) - cmdRouter.GET("/dbs/:version", baseApi.ListDBNameByVersion) + cmdRouter.GET("/dbs/:name", baseApi.ListDBNameByVersion) cmdRouter.POST("/redis/search", baseApi.SearchRedis) withRecordRouter.POST("/redis", baseApi.SetRedis) withRecordRouter.POST("/redis/del", baseApi.DeleteRedis) - withRecordRouter.POST("/redis/clean/:db", baseApi.CleanRedis) + withRecordRouter.POST("/redis/cleanall", baseApi.CleanRedis) + withRecordRouter.POST("/redis/status", baseApi.LoadRedisStatus) + withRecordRouter.POST("/redis/conf/update", baseApi.UpdateRedisConf) + withRecordRouter.POST("/redis/conf", baseApi.LoadRedisConf) + cmdRouter.GET("/redis/versions", baseApi.LoadRedisRunningVersion) } } diff --git a/frontend/src/api/interface/database.ts b/frontend/src/api/interface/database.ts index 87c5f22d5..169cf05d4 100644 --- a/frontend/src/api/interface/database.ts +++ b/frontend/src/api/interface/database.ts @@ -2,18 +2,18 @@ import { ReqPage } from '.'; export namespace Database { export interface Search extends ReqPage { - version: string; + mysqlName: string; } export interface SearchBackupRecord extends ReqPage { - version: string; + mysqlName: string; dbName: string; } export interface Backup { - version: string; + mysqlName: string; dbName: string; } export interface Recover { - version: string; + mysqlName: string; dbName: string; backupName: string; } @@ -32,10 +32,11 @@ export namespace Database { port: number; password: string; remoteConn: boolean; + mysqlKey: string; } export interface MysqlDBCreate { name: string; - version: string; + mysqlName: string; format: string; username: string; password: string; @@ -43,7 +44,7 @@ export namespace Database { description: string; } export interface MysqlVariables { - version: string; + mysqlName: string; binlog_cache_size: number; innodb_buffer_pool_size: number; innodb_log_buffer_size: number; @@ -98,16 +99,29 @@ export namespace Database { } export interface ChangeInfo { id: number; - version: string; + mysqlName: string; operation: string; value: string; } // redis export interface SearchRedisWithPage extends ReqPage { + redisName: string; db: number; } + export interface RedisBaseReq { + redisName: string; + db: number; + } + export interface RedisConfUpdate { + redisName: string; + db: number; + paramName: string; + value: string; + } export interface RedisData { + redisName: string; + db: number; key: string; value: string; type: string; @@ -115,14 +129,42 @@ export namespace Database { expiration: number; } export interface RedisDataSet { + redisName: string; db: number; key: string; value: string; expiration: number; } - export interface RedisDelBatch { + redisName: string; db: number; names: Array; } + export interface RedisStatus { + tcp_port: string; + uptime_in_days: string; + connected_clients: string; + used_memory: string; + used_memory_rss: string; + used_memory_peak: string; + mem_fragmentation_ratio: string; + total_connections_received: string; + total_commands_processed: string; + instantaneous_ops_per_sec: string; + keyspace_hits: string; + keyspace_misses: string; + latest_fork_usec: string; + } + export interface RedisConf { + timeout: number; + maxclients: number; + databases: number; + requirepass: string; + maxmemory: number; + + dir: string; + appendonly: string; + appendfsync: string; + save: string; + } } diff --git a/frontend/src/api/modules/database.ts b/frontend/src/api/modules/database.ts index fa6e2e620..fca5a4f84 100644 --- a/frontend/src/api/modules/database.ts +++ b/frontend/src/api/modules/database.ts @@ -56,6 +56,18 @@ export const setRedis = (params: Database.RedisDataSet) => { export const deleteRedisKey = (params: Database.RedisDelBatch) => { return http.post(`/databases/redis/del`, params); }; -export const cleanRedisKey = (db: number) => { - return http.post(`/databases/redis/clean/${db}`); +export const cleanRedisKey = (params: Database.RedisBaseReq) => { + return http.post(`/databases/redis/clean`, params); +}; +export const loadRedisStatus = (params: Database.RedisBaseReq) => { + return http.post(`/databases/redis/status`, params); +}; +export const loadRedisConf = (params: Database.RedisBaseReq) => { + return http.post(`/databases/redis/conf`, params); +}; +export const updateRedisConf = (params: Database.RedisConfUpdate) => { + return http.post(`/databases/redis/conf/update`, params); +}; +export const loadRedisVersions = () => { + return http.get(`/databases/redis/versions`); }; diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 1c277943c..49d8f7881 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -228,6 +228,36 @@ export default { expirationHelper: '有效期为 0 表示永久', forever: '永久', second: '秒', + timeout: '超时时间', + timeoutHelper: '空闲连接超时时间,0表示不断开', + maxclients: '最大连接数', + requirepass: '密码', + requirepassHelper: '留空代表没有设置密码', + databases: '数据库数量', + maxmemory: '最大内存使用', + maxmemoryHelper: '0 表示不做限制', + tcpPort: '当前监听端口', + uptimeInDays: '已运行天数', + connectedClients: '连接的客户端数量', + usedMemory: 'Redis 历史分配内存的峰值', + usedMemoryRss: 'Redis 当前占用的系统内存总量', + memFragmentationRatio: '内存碎片比率', + totalConnectionsReceived: '运行以来连接过的客户端的总数量', + totalCommandsProcessed: '运行以来执行过的命令的总数量', + instantaneousOpsPerSec: '服务器每秒钟执行的命令数量', + keyspaceHits: '查找数据库键成功的次数', + keyspaceMisses: '查找数据库键失败的次数', + hit: '查找数据库键命中率', + latestForkUsec: '最近一次 fork() 操作耗费的微秒数', + + persistence: '持久化', + persistenceDir: '持久化路径', + persistenceDirHelper: '设置后将在选择的目录下新建 redis_cache 目录并赋予 redis 权限', + aofPersistence: 'AOF 持久化', + rdbPersistence: 'RDB 持久化', + drbHelper1: '秒內,插入', + drbHelper2: '条数据', + drbHelper3: '符合任意一个条件将会触发RDB持久化', }, container: { operatorHelper: '将对选中容器进行 {0} 操作,是否继续?', diff --git a/frontend/src/views/database/mysql/backup/index.vue b/frontend/src/views/database/mysql/backup/index.vue index 8e297ce1e..9fe14411d 100644 --- a/frontend/src/views/database/mysql/backup/index.vue +++ b/frontend/src/views/database/mysql/backup/index.vue @@ -52,14 +52,14 @@ const paginationConfig = reactive({ }); const backupVisiable = ref(false); -const version = ref(); +const mysqlName = ref(); const dbName = ref(); interface DialogProps { - version: string; + mysqlName: string; dbName: string; } const acceptParams = (params: DialogProps): void => { - version.value = params.version; + mysqlName.value = params.mysqlName; dbName.value = params.dbName; backupVisiable.value = true; search(); @@ -69,7 +69,7 @@ const search = async () => { let params = { page: paginationConfig.currentPage, pageSize: paginationConfig.pageSize, - version: version.value, + mysqlName: mysqlName.value, dbName: dbName.value, }; const res = await searchBackupRecords(params); @@ -79,7 +79,7 @@ const search = async () => { const onBackup = async () => { let params = { - version: version.value, + mysqlName: mysqlName.value, dbName: dbName.value, }; await backup(params); @@ -89,7 +89,7 @@ const onBackup = async () => { const onRecover = async (row: Backup.RecordInfo) => { let params = { - version: version.value, + mysqlName: mysqlName.value, dbName: dbName.value, backupName: row.fileDir + row.fileName, }; diff --git a/frontend/src/views/database/mysql/create/index.vue b/frontend/src/views/database/mysql/create/index.vue index aad897250..37dc55539 100644 --- a/frontend/src/views/database/mysql/create/index.vue +++ b/frontend/src/views/database/mysql/create/index.vue @@ -60,7 +60,7 @@ import { addMysqlDB } from '@/api/modules/database'; const createVisiable = ref(false); const form = reactive({ name: '', - version: '', + mysqlName: '', format: '', username: '', password: '', @@ -79,11 +79,11 @@ type FormInstance = InstanceType; const formRef = ref(); interface DialogProps { - version: string; + mysqlName: string; } const acceptParams = (params: DialogProps): void => { form.name = ''; - form.version = params.version; + form.mysqlName = params.mysqlName; form.format = 'utf8mb4'; form.username = ''; form.password = ''; diff --git a/frontend/src/views/database/mysql/index.vue b/frontend/src/views/database/mysql/index.vue index b66bcfd76..129118943 100644 --- a/frontend/src/views/database/mysql/index.vue +++ b/frontend/src/views/database/mysql/index.vue @@ -2,9 +2,9 @@
- {{ version }} + {{ mysqlName }}