From bfe2b95334d21bf411dd20b18c341f0c7c6cb684 Mon Sep 17 00:00:00 2001 From: ssongliu Date: Wed, 2 Nov 2022 18:30:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=20mysql=E3=80=81redi?= =?UTF-8?q?s=20=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/database_mysql.go | 29 +++ backend/app/api/v1/database_redis.go | 27 +++ backend/app/dto/database.go | 16 +- backend/app/service/database_redis.go | 53 ++++- backend/router/ro_database.go | 3 + frontend/src/api/interface/database.ts | 16 +- frontend/src/api/modules/database.ts | 8 +- .../views/database/mysql/setting/index.vue | 16 +- frontend/src/views/database/redis/index.vue | 20 +- .../database/redis/persistence/index.vue | 40 ++-- .../views/database/redis/setting/index.vue | 185 +++++++++--------- .../src/views/database/redis/status/index.vue | 146 +++++++------- .../views/database/redis/terminal/index.vue | 4 +- 13 files changed, 357 insertions(+), 206 deletions(-) diff --git a/backend/app/api/v1/database_mysql.go b/backend/app/api/v1/database_mysql.go index 7db1aeda2..3f41f3bb1 100644 --- a/backend/app/api/v1/database_mysql.go +++ b/backend/app/api/v1/database_mysql.go @@ -1,7 +1,10 @@ package v1 import ( + "bufio" "errors" + "fmt" + "os" "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" "github.com/1Panel-dev/1Panel/backend/app/dto" @@ -61,6 +64,32 @@ func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) { helper.SuccessWithData(c, nil) } +func (b *BaseApi) UpdateMysqlConfByFile(c *gin.Context) { + var req dto.MysqlConfUpdateByFile + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + mysqlInfo, err := mysqlService.LoadBaseInfo(req.MysqlName) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + path := fmt.Sprintf("/opt/1Panel/data/apps/%s/%s/conf/my.cnf", mysqlInfo.MysqlKey, mysqlInfo.Name) + file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + defer file.Close() + write := bufio.NewWriter(file) + _, _ = write.WriteString(req.File) + write.Flush() + + helper.SuccessWithData(c, nil) +} + func (b *BaseApi) SearchMysql(c *gin.Context) { var req dto.SearchDBWithPage if err := c.ShouldBindJSON(&req); err != nil { diff --git a/backend/app/api/v1/database_redis.go b/backend/app/api/v1/database_redis.go index fa4770e69..900f2130c 100644 --- a/backend/app/api/v1/database_redis.go +++ b/backend/app/api/v1/database_redis.go @@ -1,8 +1,10 @@ package v1 import ( + "bufio" "context" "fmt" + "os" "strconv" "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" @@ -63,6 +65,31 @@ func (b *BaseApi) UpdateRedisConf(c *gin.Context) { helper.SuccessWithData(c, nil) } +func (b *BaseApi) UpdateRedisConfByFile(c *gin.Context) { + var req dto.RedisConfUpdateByFile + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + redisInfo, err := redisService.LoadConf() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + path := fmt.Sprintf("/opt/1Panel/data/apps/redis/%s/conf/redis.conf", redisInfo.Name) + file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + defer file.Close() + write := bufio.NewWriter(file) + _, _ = write.WriteString(req.File) + write.Flush() + + helper.SuccessWithData(c, nil) +} + func (b *BaseApi) RedisExec(c *gin.Context) { redisConf, err := redisService.LoadConf() if err != nil { diff --git a/backend/app/dto/database.go b/backend/app/dto/database.go index 366ad64fb..c36eeea2d 100644 --- a/backend/app/dto/database.go +++ b/backend/app/dto/database.go @@ -99,6 +99,10 @@ type MysqlVariablesUpdate struct { TableOpenCache int64 `json:"table_open_cache" validate:"required"` MaxConnections int64 `json:"max_connections" validate:"required"` } +type MysqlConfUpdateByFile struct { + MysqlName string `json:"mysqlName" validate:"required"` + File string `json:"file"` +} type ChangeDBInfo struct { ID uint `json:"id"` @@ -139,10 +143,14 @@ type RecoverDB struct { // redis type RedisConfUpdate struct { - RedisName string `json:"redisName" validate:"required"` - DB int `json:"db"` - ParamName string `json:"paramName" validate:"required"` - Value string `json:"value"` + Timeout string `json:"timeout"` + Maxclients string `json:"maxclients"` + Databases string `json:"databases"` + Requirepass string `json:"requirepass"` + Maxmemory string `json:"maxmemory"` +} +type RedisConfUpdateByFile struct { + File string `json:"file"` } type RedisConf struct { diff --git a/backend/app/service/database_redis.go b/backend/app/service/database_redis.go index bd240dbca..b8c7db244 100644 --- a/backend/app/service/database_redis.go +++ b/backend/app/service/database_redis.go @@ -1,8 +1,11 @@ package service import ( + "bufio" "encoding/json" "fmt" + "io" + "os" "strings" "github.com/1Panel-dev/1Panel/backend/app/dto" @@ -41,17 +44,44 @@ func newRedisClient() (*redis.Client, error) { } func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error { - client, err := newRedisClient() + redisInfo, err := mysqlRepo.LoadRedisBaseInfo() 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 { + file, err := os.OpenFile(fmt.Sprintf("/opt/1Panel/data/apps/redis/%s/conf/redis.conf", redisInfo.Name), os.O_RDWR, 0666) + if err != nil { return err } + defer file.Close() + reader := bufio.NewReader(file) + pos := int64(0) + for { + line, err := reader.ReadString('\n') + if err != nil { + if err == io.EOF { + break + } else { + return err + } + } + if bytes := updateConfFile(line, "timeout", req.Timeout); len(bytes) != 0 { + _, _ = file.WriteAt(bytes, pos) + } + if bytes := updateConfFile(line, "maxclients", req.Maxclients); len(bytes) != 0 { + _, _ = file.WriteAt(bytes, pos) + } + if bytes := updateConfFile(line, "databases", req.Databases); len(bytes) != 0 { + _, _ = file.WriteAt(bytes, pos) + } + if bytes := updateConfFile(line, "requirepass", req.Requirepass); len(bytes) != 0 { + _, _ = file.WriteAt(bytes, pos) + } + if bytes := updateConfFile(line, "maxmemory", req.Maxmemory); len(bytes) != 0 { + _, _ = file.WriteAt(bytes, pos) + } + pos += int64(len(line)) + } return nil } @@ -129,3 +159,16 @@ func configGetStr(client *redis.Client, param string) string { } return "" } + +func updateConfFile(line, param string, value string) []byte { + var bytes []byte + if strings.HasPrefix(line, param) || strings.HasPrefix(line, "# "+param) { + if len(value) == 0 || value == "0" { + bytes = []byte(fmt.Sprintf("# %s", param)) + } else { + bytes = []byte(fmt.Sprintf("%s %v", param, value)) + } + return bytes + } + return bytes +} diff --git a/backend/router/ro_database.go b/backend/router/ro_database.go index c578cf097..048f734e8 100644 --- a/backend/router/ro_database.go +++ b/backend/router/ro_database.go @@ -28,6 +28,7 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { withRecordRouter.POST("/backups/search", baseApi.SearchDBBackups) withRecordRouter.POST("/del", baseApi.DeleteMysql) withRecordRouter.POST("/variables/update", baseApi.UpdateMysqlVariables) + withRecordRouter.POST("/conf/update/byfile", baseApi.UpdateMysqlConfByFile) cmdRouter.POST("/search", baseApi.SearchMysql) cmdRouter.GET("/variables/:name", baseApi.LoadVariables) cmdRouter.GET("/status/:name", baseApi.LoadStatus) @@ -39,5 +40,7 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { cmdRouter.GET("/redis/status", baseApi.LoadRedisStatus) cmdRouter.GET("/redis/conf", baseApi.LoadRedisConf) cmdRouter.GET("/redis/exec", baseApi.RedisExec) + cmdRouter.POST("/redis/conf/update", baseApi.UpdateRedisConf) + cmdRouter.POST("/redis/conf/update/byfile", baseApi.UpdateRedisConfByFile) } } diff --git a/frontend/src/api/interface/database.ts b/frontend/src/api/interface/database.ts index 6a72626cb..e7167803c 100644 --- a/frontend/src/api/interface/database.ts +++ b/frontend/src/api/interface/database.ts @@ -34,6 +34,10 @@ export namespace Database { remoteConn: boolean; mysqlKey: string; } + export interface MysqlConfUpdateByFile { + mysqlName: string; + file: string; + } export interface MysqlDBCreate { name: string; mysqlName: string; @@ -106,10 +110,14 @@ export namespace Database { // redis export interface RedisConfUpdate { - redisName: string; - db: number; - paramName: string; - value: string; + timeout: string; + maxclients: string; + databases: string; + requirepass: string; + maxmemory: string; + } + export interface RedisConfUpdateByFile { + file: string; } export interface RedisStatus { tcp_port: string; diff --git a/frontend/src/api/modules/database.ts b/frontend/src/api/modules/database.ts index 9b1c39302..880078423 100644 --- a/frontend/src/api/modules/database.ts +++ b/frontend/src/api/modules/database.ts @@ -29,6 +29,9 @@ export const updateMysqlDBInfo = (params: Database.ChangeInfo) => { export const updateMysqlVariables = (params: Database.MysqlVariables) => { return http.post(`/databases/variables/update`, params); }; +export const updateMysqlConfByFile = (params: Database.MysqlConfUpdateByFile) => { + return http.post(`/databases/conf/update/byfile`, params); +}; export const deleteMysqlDB = (params: { ids: number[] }) => { return http.post(`/databases/del`, params); }; @@ -57,5 +60,8 @@ export const RedisPersistenceConf = () => { return http.get(`/databases/redis/persistence/conf`); }; export const updateRedisConf = (params: Database.RedisConfUpdate) => { - return http.get(`/databases/redis/conf/update`, params); + return http.post(`/databases/redis/conf/update`, params); +}; +export const updateRedisConfByFile = (params: Database.RedisConfUpdateByFile) => { + return http.post(`/databases/redis/conf/update/byfile`, params); }; diff --git a/frontend/src/views/database/mysql/setting/index.vue b/frontend/src/views/database/mysql/setting/index.vue index 8ec0f8ad8..2b35e21b0 100644 --- a/frontend/src/views/database/mysql/setting/index.vue +++ b/frontend/src/views/database/mysql/setting/index.vue @@ -65,11 +65,7 @@ v-model="mysqlConf" :readOnly="true" /> - + {{ $t('commons.button.save') }} @@ -324,6 +320,7 @@ import { loadMysqlBaseInfo, loadMysqlStatus, loadMysqlVariables, + updateMysqlConfByFile, updateMysqlDBInfo, updateMysqlVariables, } from '@/api/modules/database'; @@ -447,6 +444,15 @@ function callback(error: any) { } } +const onSaveFile = async () => { + let param = { + mysqlName: mysqlName.value, + file: mysqlConf.value, + }; + await updateMysqlConfByFile(param); + ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); +}; + const loadBaseInfo = async () => { const res = await loadMysqlBaseInfo(mysqlName.value); baseInfo.name = res.data?.name; diff --git a/frontend/src/views/database/redis/index.vue b/frontend/src/views/database/redis/index.vue index 23c155dce..99ba33e2a 100644 --- a/frontend/src/views/database/redis/index.vue +++ b/frontend/src/views/database/redis/index.vue @@ -14,11 +14,10 @@ {{ $t('database.terminal') }} - - - - - + + + + @@ -26,11 +25,13 @@ import Submenu from '@/views/database/index.vue'; import Status from '@/views/database/redis/status/index.vue'; import Setting from '@/views/database/redis/setting/index.vue'; +import Persistence from '@/views/database/redis/persistence/index.vue'; import Terminal from '@/views/database/redis/terminal/index.vue'; import { onMounted, ref } from 'vue'; const statusRef = ref(); const settingRef = ref(); +const persistenceRef = ref(); const terminalRef = ref(); const changeView = async (params: string) => { @@ -38,16 +39,25 @@ const changeView = async (params: string) => { case 'status': settingRef.value!.onClose(); terminalRef.value!.onClose(); + persistenceRef.value!.onClose(); statusRef.value!.acceptParams(params); break; case 'setting': statusRef.value!.onClose(); terminalRef.value!.onClose(); + persistenceRef.value!.onClose(); settingRef.value!.acceptParams(params); break; + case 'persistence': + statusRef.value!.onClose(); + settingRef.value!.onClose(); + terminalRef.value!.onClose(); + persistenceRef.value!.acceptParams(params); + break; case 'terminal': statusRef.value!.onClose(); settingRef.value!.onClose(); + persistenceRef.value!.onClose(); terminalRef.value!.acceptParams(params); break; } diff --git a/frontend/src/views/database/redis/persistence/index.vue b/frontend/src/views/database/redis/persistence/index.vue index 88912f3d7..74c14ac64 100644 --- a/frontend/src/views/database/redis/persistence/index.vue +++ b/frontend/src/views/database/redis/persistence/index.vue @@ -1,24 +1,26 @@ diff --git a/frontend/src/views/database/redis/setting/index.vue b/frontend/src/views/database/redis/setting/index.vue index f5909ebc2..6daece921 100644 --- a/frontend/src/views/database/redis/setting/index.vue +++ b/frontend/src/views/database/redis/setting/index.vue @@ -1,79 +1,81 @@