From c56435970a39eac5c51bb4baab0368b32fbfa890 Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Mon, 13 May 2024 22:40:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=95=B0=E6=8D=AE=E5=BA=93=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=20Redis=20=E5=88=87=E6=8D=A2=20(#5001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #3927 --- backend/app/api/v1/backup.go | 2 +- backend/app/api/v1/database_redis.go | 50 ++-- backend/app/api/v1/terminal.go | 16 +- backend/app/dto/database.go | 16 +- backend/app/service/backup.go | 2 +- backend/app/service/backup_redis.go | 7 +- backend/app/service/database_redis.go | 68 +----- backend/router/ro_database.go | 7 +- cmd/server/docs/docs.go | 172 +++++++++++--- cmd/server/docs/swagger.json | 172 +++++++++++--- cmd/server/docs/swagger.yaml | 114 ++++++++-- frontend/src/api/interface/database.ts | 16 +- frontend/src/api/modules/database.ts | 22 +- frontend/src/components/app-status/index.vue | 3 +- frontend/src/components/terminal/index.vue | 12 +- frontend/src/views/database/redis/index.vue | 213 ++++++++++++++---- .../views/database/redis/password/index.vue | 29 +-- .../views/database/redis/setting/index.vue | 17 +- .../redis/setting/persistence/index.vue | 12 +- .../database/redis/setting/status/index.vue | 5 +- .../src/views/host/terminal/command/index.vue | 4 +- 21 files changed, 671 insertions(+), 288 deletions(-) diff --git a/backend/app/api/v1/backup.go b/backend/app/api/v1/backup.go index ae358bf92..93a671b6d 100644 --- a/backend/app/api/v1/backup.go +++ b/backend/app/api/v1/backup.go @@ -343,7 +343,7 @@ func (b *BaseApi) Backup(c *gin.Context) { return } case "redis": - if err := backupService.RedisBackup(); err != nil { + if err := backupService.RedisBackup(req); 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 489d1645c..720879763 100644 --- a/backend/app/api/v1/database_redis.go +++ b/backend/app/api/v1/database_redis.go @@ -12,11 +12,17 @@ import ( // @Tags Database Redis // @Summary Load redis status info // @Description 获取 redis 状态信息 +// @Accept json +// @Param request body dto.OperationWithName true "request" // @Success 200 {object} dto.RedisStatus // @Security ApiKeyAuth // @Router /databases/redis/status [get] func (b *BaseApi) LoadRedisStatus(c *gin.Context) { - data, err := redisService.LoadStatus() + var req dto.OperationWithName + if err := helper.CheckBind(&req, c); err != nil { + return + } + data, err := redisService.LoadStatus(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -28,11 +34,17 @@ func (b *BaseApi) LoadRedisStatus(c *gin.Context) { // @Tags Database Redis // @Summary Load redis conf // @Description 获取 redis 配置信息 +// @Accept json +// @Param request body dto.OperationWithName true "request" // @Success 200 {object} dto.RedisConf // @Security ApiKeyAuth // @Router /databases/redis/conf [get] func (b *BaseApi) LoadRedisConf(c *gin.Context) { - data, err := redisService.LoadConf() + var req dto.OperationWithName + if err := helper.CheckBind(&req, c); err != nil { + return + } + data, err := redisService.LoadConf(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -44,11 +56,17 @@ func (b *BaseApi) LoadRedisConf(c *gin.Context) { // @Tags Database Redis // @Summary Load redis persistence conf // @Description 获取 redis 持久化配置 +// @Accept json +// @Param request body dto.OperationWithName true "request" // @Success 200 {object} dto.RedisPersistence // @Security ApiKeyAuth // @Router /databases/redis/persistence/conf [get] func (b *BaseApi) LoadPersistenceConf(c *gin.Context) { - data, err := redisService.LoadPersistenceConf() + var req dto.OperationWithName + if err := helper.CheckBind(&req, c); err != nil { + return + } + data, err := redisService.LoadPersistenceConf(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -131,29 +149,3 @@ func (b *BaseApi) UpdateRedisPersistenceConf(c *gin.Context) { } helper.SuccessWithData(c, nil) } - -// @Tags Database Redis -// @Summary Page redis backups -// @Description 获取 redis 备份记录分页 -// @Accept json -// @Param request body dto.PageInfo true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /databases/redis/backup/search [post] -func (b *BaseApi) RedisBackupList(c *gin.Context) { - var req dto.PageInfo - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := redisService.SearchBackupListWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} diff --git a/backend/app/api/v1/terminal.go b/backend/app/api/v1/terminal.go index 6d6651ca3..6d2e68bde 100644 --- a/backend/app/api/v1/terminal.go +++ b/backend/app/api/v1/terminal.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/1Panel-dev/1Panel/backend/utils/copier" @@ -86,23 +87,24 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) { if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) { return } - redisConf, err := redisService.LoadConf() - if wshandleError(wsConn, errors.WithMessage(err, "load redis container failed")) { + name := c.Query("name") + redisInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Type: "redis", Name: name}) + if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) { return } defer wsConn.Close() commands := []string{"redis-cli"} - if len(redisConf.Requirepass) != 0 { - commands = []string{"redis-cli", "-a", redisConf.Requirepass, "--no-auth-warning"} + if len(redisInfo.Password) != 0 { + commands = []string{"redis-cli", "-a", redisInfo.Password, "--no-auth-warning"} } - pidMap := loadMapFromDockerTop(redisConf.ContainerName) - itemCmds := append([]string{"exec", "-it", redisConf.ContainerName}, commands...) + pidMap := loadMapFromDockerTop(redisInfo.Password) + itemCmds := append([]string{"exec", "-it", redisInfo.ContainerName}, commands...) slave, err := terminal.NewCommand(itemCmds) if wshandleError(wsConn, err) { return } - defer killBash(redisConf.ContainerName, strings.Join(commands, " "), pidMap) + defer killBash(redisInfo.ContainerName, strings.Join(commands, " "), pidMap) defer slave.Close() tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false) diff --git a/backend/app/dto/database.go b/backend/app/dto/database.go index 5f4901710..852285e3c 100644 --- a/backend/app/dto/database.go +++ b/backend/app/dto/database.go @@ -131,7 +131,7 @@ type MysqlStatus struct { } type MysqlVariables struct { - BinlogCacheSize string `json:"binlog_cache_size"` + BinlogCacheSize string `json:"binlog_cache_size"` InnodbBufferPoolSize string `json:"innodb_buffer_pool_size"` InnodbLogBufferSize string `json:"innodb_log_buffer_size"` JoinBufferSize string `json:"join_buffer_size"` @@ -165,26 +165,26 @@ type MysqlVariablesUpdateHelper struct { // redis type ChangeRedisPass struct { - Value string `json:"value" validate:"required"` + Database string `json:"database" validate:"required"` + Value string `json:"value" validate:"required"` } type RedisConfUpdate struct { + Database string `json:"database" validate:"required"` Timeout string `json:"timeout"` Maxclients string `json:"maxclients"` Maxmemory string `json:"maxmemory"` } type RedisConfPersistenceUpdate struct { + Database string `json:"database" validate:"required"` Type string `json:"type" validate:"required,oneof=aof rbd"` Appendonly string `json:"appendonly"` Appendfsync string `json:"appendfsync"` Save string `json:"save"` } -type RedisConfUpdateByFile struct { - File string `json:"file" validate:"required"` - RestartNow bool `json:"restartNow"` -} type RedisConf struct { + Database string `json:"database" validate:"required"` Name string `json:"name"` Port int64 `json:"port"` ContainerName string `json:"containerName"` @@ -195,12 +195,14 @@ type RedisConf struct { } type RedisPersistence struct { + Database string `json:"database" validate:"required"` Appendonly string `json:"appendonly"` Appendfsync string `json:"appendfsync"` Save string `json:"save"` } type RedisStatus struct { + Database string `json:"database" validate:"required"` TcpPort string `json:"tcp_port"` UptimeInDays string `json:"uptime_in_days"` ConnectedClients string `json:"connected_clients"` @@ -217,12 +219,14 @@ type RedisStatus struct { } type DatabaseFileRecords struct { + Database string `json:"database" validate:"required"` FileName string `json:"fileName"` FileDir string `json:"fileDir"` CreatedAt string `json:"createdAt"` Size int `json:"size"` } type RedisBackupRecover struct { + Database string `json:"database" validate:"required"` FileName string `json:"fileName"` FileDir string `json:"fileDir"` } diff --git a/backend/app/service/backup.go b/backend/app/service/backup.go index 7a1a1f878..cc84b56fa 100644 --- a/backend/app/service/backup.go +++ b/backend/app/service/backup.go @@ -49,7 +49,7 @@ type IBackupService interface { MysqlRecoverByUpload(req dto.CommonRecover) error PostgresqlRecoverByUpload(req dto.CommonRecover) error - RedisBackup() error + RedisBackup(db dto.CommonBackup) error RedisRecover(db dto.CommonRecover) error WebsiteBackup(db dto.CommonBackup) error diff --git a/backend/app/service/backup_redis.go b/backend/app/service/backup_redis.go index a4a945a45..694e30ec1 100644 --- a/backend/app/service/backup_redis.go +++ b/backend/app/service/backup_redis.go @@ -20,12 +20,12 @@ import ( "github.com/pkg/errors" ) -func (u *BackupService) RedisBackup() error { +func (u *BackupService) RedisBackup(db dto.CommonBackup) error { localDir, err := loadLocalDir() if err != nil { return err } - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", "") + redisInfo, err := appInstallRepo.LoadBaseInfo("redis", db.Name) if err != nil { return err } @@ -51,6 +51,7 @@ func (u *BackupService) RedisBackup() error { } record := &model.BackupRecord{ Type: "redis", + Name: db.Name, Source: "LOCAL", BackupType: "LOCAL", FileDir: itemDir, @@ -64,7 +65,7 @@ func (u *BackupService) RedisBackup() error { } func (u *BackupService) RedisRecover(req dto.CommonRecover) error { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", "") + redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Name) if err != nil { return err } diff --git a/backend/app/service/database_redis.go b/backend/app/service/database_redis.go index 4423e1200..d57cb5d1e 100644 --- a/backend/app/service/database_redis.go +++ b/backend/app/service/database_redis.go @@ -6,8 +6,6 @@ import ( "fmt" "os" "os/exec" - "path" - "path/filepath" "strings" "github.com/1Panel-dev/1Panel/backend/app/dto" @@ -23,11 +21,9 @@ type IRedisService interface { UpdatePersistenceConf(req dto.RedisConfPersistenceUpdate) error ChangePassword(info dto.ChangeRedisPass) error - LoadStatus() (*dto.RedisStatus, error) - LoadConf() (*dto.RedisConf, error) - LoadPersistenceConf() (*dto.RedisPersistence, error) - - SearchBackupListWithPage(req dto.PageInfo) (int64, interface{}, error) + LoadStatus(req dto.OperationWithName) (*dto.RedisStatus, error) + LoadConf(req dto.OperationWithName) (*dto.RedisConf, error) + LoadPersistenceConf(req dto.OperationWithName) (*dto.RedisPersistence, error) } func NewIRedisService() IRedisService { @@ -35,7 +31,7 @@ func NewIRedisService() IRedisService { } func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", "") + redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Database) if err != nil { return err } @@ -55,7 +51,7 @@ func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error { } func (u *RedisService) ChangePassword(req dto.ChangeRedisPass) error { - if err := updateInstallInfoInDB("redis", "", "password", req.Value); err != nil { + if err := updateInstallInfoInDB("redis", req.Database, "password", req.Value); err != nil { return err } if err := updateInstallInfoInDB("redis-commander", "", "password", req.Value); err != nil { @@ -66,7 +62,7 @@ func (u *RedisService) ChangePassword(req dto.ChangeRedisPass) error { } func (u *RedisService) UpdatePersistenceConf(req dto.RedisConfPersistenceUpdate) error { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", "") + redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Database) if err != nil { return err } @@ -88,8 +84,8 @@ func (u *RedisService) UpdatePersistenceConf(req dto.RedisConfPersistenceUpdate) return nil } -func (u *RedisService) LoadStatus() (*dto.RedisStatus, error) { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", "") +func (u *RedisService) LoadStatus(req dto.OperationWithName) (*dto.RedisStatus, error) { + redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Name) if err != nil { return nil, err } @@ -116,8 +112,8 @@ func (u *RedisService) LoadStatus() (*dto.RedisStatus, error) { return &info, nil } -func (u *RedisService) LoadConf() (*dto.RedisConf, error) { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", "") +func (u *RedisService) LoadConf(req dto.OperationWithName) (*dto.RedisConf, error) { + redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Name) if err != nil { return nil, err } @@ -133,8 +129,8 @@ func (u *RedisService) LoadConf() (*dto.RedisConf, error) { return &item, nil } -func (u *RedisService) LoadPersistenceConf() (*dto.RedisPersistence, error) { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", "") +func (u *RedisService) LoadPersistenceConf(req dto.OperationWithName) (*dto.RedisPersistence, error) { + redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Name) if err != nil { return nil, err } @@ -151,46 +147,6 @@ func (u *RedisService) LoadPersistenceConf() (*dto.RedisPersistence, error) { return &item, nil } -func (u *RedisService) SearchBackupListWithPage(req dto.PageInfo) (int64, interface{}, error) { - var ( - list []dto.DatabaseFileRecords - backDatas []dto.DatabaseFileRecords - ) - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", "") - if err != nil { - return 0, nil, err - } - localDir, err := loadLocalDir() - if err != nil { - return 0, nil, err - } - backupDir := path.Join(localDir, fmt.Sprintf("database/redis/%s", redisInfo.Name)) - _ = filepath.Walk(backupDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return nil - } - if !info.IsDir() { - list = append(list, dto.DatabaseFileRecords{ - CreatedAt: info.ModTime().Format("2006-01-02 15:04:05"), - Size: int(info.Size()), - FileDir: backupDir, - FileName: info.Name(), - }) - } - return nil - }) - total, start, end := len(list), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - backDatas = make([]dto.DatabaseFileRecords, 0) - } else { - if end >= total { - end = total - } - backDatas = list[start:end] - } - return int64(total), backDatas, nil -} - func configGetStr(containerName, password, param string) (string, error) { commands := append(redisExec(containerName, password), []string{"config", "get", param}...) cmd := exec.Command("docker", commands...) diff --git a/backend/router/ro_database.go b/backend/router/ro_database.go index f4b2d170a..3cc26d9f8 100644 --- a/backend/router/ro_database.go +++ b/backend/router/ro_database.go @@ -35,12 +35,11 @@ func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) { cmdRouter.POST("/remote", baseApi.LoadRemoteAccess) cmdRouter.GET("/options", baseApi.ListDBName) - cmdRouter.GET("/redis/persistence/conf", baseApi.LoadPersistenceConf) - cmdRouter.GET("/redis/status", baseApi.LoadRedisStatus) - cmdRouter.GET("/redis/conf", baseApi.LoadRedisConf) + cmdRouter.POST("/redis/persistence/conf", baseApi.LoadPersistenceConf) + cmdRouter.POST("/redis/status", baseApi.LoadRedisStatus) + cmdRouter.POST("/redis/conf", baseApi.LoadRedisConf) cmdRouter.GET("/redis/exec", baseApi.RedisWsSsh) cmdRouter.POST("/redis/password", baseApi.ChangeRedisPassword) - cmdRouter.POST("/redis/backup/search", baseApi.RedisBackupList) cmdRouter.POST("/redis/conf/update", baseApi.UpdateRedisConf) cmdRouter.POST("/redis/persistence/update", baseApi.UpdateRedisPersistenceConf) diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index bcc210e61..81b38e733 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -5109,21 +5109,21 @@ const docTemplate = `{ } } }, - "/databases/redis/backup/search": { - "post": { + "/databases/redis/conf": { + "get": { "security": [ { "ApiKeyAuth": [] } ], - "description": "获取 redis 备份记录分页", + "description": "获取 redis 配置信息", "consumes": [ "application/json" ], "tags": [ "Database Redis" ], - "summary": "Page redis backups", + "summary": "Load redis conf", "parameters": [ { "description": "request", @@ -5131,32 +5131,10 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.PageInfo" + "$ref": "#/definitions/dto.OperationWithName" } } ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/databases/redis/conf": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 配置信息", - "tags": [ - "Database Redis" - ], - "summary": "Load redis conf", "responses": { "200": { "description": "OK", @@ -5255,10 +5233,24 @@ const docTemplate = `{ } ], "description": "获取 redis 持久化配置", + "consumes": [ + "application/json" + ], "tags": [ "Database Redis" ], "summary": "Load redis persistence conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithName" + } + } + ], "responses": { "200": { "description": "OK", @@ -5317,10 +5309,24 @@ const docTemplate = `{ } ], "description": "获取 redis 状态信息", + "consumes": [ + "application/json" + ], "tags": [ "Database Redis" ], "summary": "Load redis status info", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithName" + } + } + ], "responses": { "200": { "description": "OK", @@ -14323,9 +14329,13 @@ const docTemplate = `{ "dto.ChangeRedisPass": { "type": "object", "required": [ + "database", "value" ], "properties": { + "database": { + "type": "string" + }, "value": { "type": "string" } @@ -14761,7 +14771,8 @@ const docTemplate = `{ "container", "image", "volume", - "network" + "network", + "buildcache" ] }, "withTagAll": { @@ -17296,10 +17307,16 @@ const docTemplate = `{ }, "dto.RedisConf": { "type": "object", + "required": [ + "database" + ], "properties": { "containerName": { "type": "string" }, + "database": { + "type": "string" + }, "maxclients": { "type": "string" }, @@ -17323,6 +17340,7 @@ const docTemplate = `{ "dto.RedisConfPersistenceUpdate": { "type": "object", "required": [ + "database", "type" ], "properties": { @@ -17332,6 +17350,9 @@ const docTemplate = `{ "appendonly": { "type": "string" }, + "database": { + "type": "string" + }, "save": { "type": "string" }, @@ -17346,7 +17367,13 @@ const docTemplate = `{ }, "dto.RedisConfUpdate": { "type": "object", + "required": [ + "database" + ], "properties": { + "database": { + "type": "string" + }, "maxclients": { "type": "string" }, @@ -17360,6 +17387,9 @@ const docTemplate = `{ }, "dto.RedisPersistence": { "type": "object", + "required": [ + "database" + ], "properties": { "appendfsync": { "type": "string" @@ -17367,6 +17397,9 @@ const docTemplate = `{ "appendonly": { "type": "string" }, + "database": { + "type": "string" + }, "save": { "type": "string" } @@ -17374,10 +17407,16 @@ const docTemplate = `{ }, "dto.RedisStatus": { "type": "object", + "required": [ + "database" + ], "properties": { "connected_clients": { "type": "string" }, + "database": { + "type": "string" + }, "instantaneous_ops_per_sec": { "type": "string" }, @@ -18578,6 +18617,9 @@ const docTemplate = `{ "dir": { "type": "string" }, + "disableCNAME": { + "type": "boolean" + }, "dnsAccount": { "$ref": "#/definitions/model.WebsiteDnsAccount" }, @@ -18599,6 +18641,12 @@ const docTemplate = `{ "message": { "type": "string" }, + "nameserver1": { + "type": "string" + }, + "nameserver2": { + "type": "string" + }, "organization": { "type": "string" }, @@ -18617,6 +18665,9 @@ const docTemplate = `{ "pushDir": { "type": "boolean" }, + "skipDNS": { + "type": "boolean" + }, "startDate": { "type": "string" }, @@ -20542,7 +20593,6 @@ const docTemplate = `{ "required": [ "id", "match", - "modifier", "name", "operate", "proxyHost", @@ -20627,7 +20677,13 @@ const docTemplate = `{ "ID": { "type": "integer" }, - "SkipDNSCheck": { + "nameservers": { + "type": "array", + "items": { + "type": "string" + } + }, + "skipDNSCheck": { "type": "boolean" } } @@ -20655,6 +20711,9 @@ const docTemplate = `{ "dir": { "type": "string" }, + "disableCNAME": { + "type": "boolean" + }, "dnsAccountId": { "type": "integer" }, @@ -20664,6 +20723,12 @@ const docTemplate = `{ "keyType": { "type": "string" }, + "nameserver1": { + "type": "string" + }, + "nameserver2": { + "type": "string" + }, "otherDomains": { "type": "string" }, @@ -20675,6 +20740,9 @@ const docTemplate = `{ }, "pushDir": { "type": "boolean" + }, + "skipDNS": { + "type": "boolean" } } }, @@ -20699,17 +20767,59 @@ const docTemplate = `{ "request.WebsiteSSLUpdate": { "type": "object", "required": [ - "id" + "acmeAccountId", + "id", + "primaryDomain", + "provider" ], "properties": { + "acmeAccountId": { + "type": "integer" + }, + "apply": { + "type": "boolean" + }, "autoRenew": { "type": "boolean" }, "description": { "type": "string" }, + "dir": { + "type": "string" + }, + "disableCNAME": { + "type": "boolean" + }, + "dnsAccountId": { + "type": "integer" + }, "id": { "type": "integer" + }, + "keyType": { + "type": "string" + }, + "nameserver1": { + "type": "string" + }, + "nameserver2": { + "type": "string" + }, + "otherDomains": { + "type": "string" + }, + "primaryDomain": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "pushDir": { + "type": "boolean" + }, + "skipDNS": { + "type": "boolean" } } }, diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index 5f2fb5d48..be737759d 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -5102,21 +5102,21 @@ } } }, - "/databases/redis/backup/search": { - "post": { + "/databases/redis/conf": { + "get": { "security": [ { "ApiKeyAuth": [] } ], - "description": "获取 redis 备份记录分页", + "description": "获取 redis 配置信息", "consumes": [ "application/json" ], "tags": [ "Database Redis" ], - "summary": "Page redis backups", + "summary": "Load redis conf", "parameters": [ { "description": "request", @@ -5124,32 +5124,10 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.PageInfo" + "$ref": "#/definitions/dto.OperationWithName" } } ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/databases/redis/conf": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 配置信息", - "tags": [ - "Database Redis" - ], - "summary": "Load redis conf", "responses": { "200": { "description": "OK", @@ -5248,10 +5226,24 @@ } ], "description": "获取 redis 持久化配置", + "consumes": [ + "application/json" + ], "tags": [ "Database Redis" ], "summary": "Load redis persistence conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithName" + } + } + ], "responses": { "200": { "description": "OK", @@ -5310,10 +5302,24 @@ } ], "description": "获取 redis 状态信息", + "consumes": [ + "application/json" + ], "tags": [ "Database Redis" ], "summary": "Load redis status info", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithName" + } + } + ], "responses": { "200": { "description": "OK", @@ -14316,9 +14322,13 @@ "dto.ChangeRedisPass": { "type": "object", "required": [ + "database", "value" ], "properties": { + "database": { + "type": "string" + }, "value": { "type": "string" } @@ -14754,7 +14764,8 @@ "container", "image", "volume", - "network" + "network", + "buildcache" ] }, "withTagAll": { @@ -17289,10 +17300,16 @@ }, "dto.RedisConf": { "type": "object", + "required": [ + "database" + ], "properties": { "containerName": { "type": "string" }, + "database": { + "type": "string" + }, "maxclients": { "type": "string" }, @@ -17316,6 +17333,7 @@ "dto.RedisConfPersistenceUpdate": { "type": "object", "required": [ + "database", "type" ], "properties": { @@ -17325,6 +17343,9 @@ "appendonly": { "type": "string" }, + "database": { + "type": "string" + }, "save": { "type": "string" }, @@ -17339,7 +17360,13 @@ }, "dto.RedisConfUpdate": { "type": "object", + "required": [ + "database" + ], "properties": { + "database": { + "type": "string" + }, "maxclients": { "type": "string" }, @@ -17353,6 +17380,9 @@ }, "dto.RedisPersistence": { "type": "object", + "required": [ + "database" + ], "properties": { "appendfsync": { "type": "string" @@ -17360,6 +17390,9 @@ "appendonly": { "type": "string" }, + "database": { + "type": "string" + }, "save": { "type": "string" } @@ -17367,10 +17400,16 @@ }, "dto.RedisStatus": { "type": "object", + "required": [ + "database" + ], "properties": { "connected_clients": { "type": "string" }, + "database": { + "type": "string" + }, "instantaneous_ops_per_sec": { "type": "string" }, @@ -18571,6 +18610,9 @@ "dir": { "type": "string" }, + "disableCNAME": { + "type": "boolean" + }, "dnsAccount": { "$ref": "#/definitions/model.WebsiteDnsAccount" }, @@ -18592,6 +18634,12 @@ "message": { "type": "string" }, + "nameserver1": { + "type": "string" + }, + "nameserver2": { + "type": "string" + }, "organization": { "type": "string" }, @@ -18610,6 +18658,9 @@ "pushDir": { "type": "boolean" }, + "skipDNS": { + "type": "boolean" + }, "startDate": { "type": "string" }, @@ -20535,7 +20586,6 @@ "required": [ "id", "match", - "modifier", "name", "operate", "proxyHost", @@ -20620,7 +20670,13 @@ "ID": { "type": "integer" }, - "SkipDNSCheck": { + "nameservers": { + "type": "array", + "items": { + "type": "string" + } + }, + "skipDNSCheck": { "type": "boolean" } } @@ -20648,6 +20704,9 @@ "dir": { "type": "string" }, + "disableCNAME": { + "type": "boolean" + }, "dnsAccountId": { "type": "integer" }, @@ -20657,6 +20716,12 @@ "keyType": { "type": "string" }, + "nameserver1": { + "type": "string" + }, + "nameserver2": { + "type": "string" + }, "otherDomains": { "type": "string" }, @@ -20668,6 +20733,9 @@ }, "pushDir": { "type": "boolean" + }, + "skipDNS": { + "type": "boolean" } } }, @@ -20692,17 +20760,59 @@ "request.WebsiteSSLUpdate": { "type": "object", "required": [ - "id" + "acmeAccountId", + "id", + "primaryDomain", + "provider" ], "properties": { + "acmeAccountId": { + "type": "integer" + }, + "apply": { + "type": "boolean" + }, "autoRenew": { "type": "boolean" }, "description": { "type": "string" }, + "dir": { + "type": "string" + }, + "disableCNAME": { + "type": "boolean" + }, + "dnsAccountId": { + "type": "integer" + }, "id": { "type": "integer" + }, + "keyType": { + "type": "string" + }, + "nameserver1": { + "type": "string" + }, + "nameserver2": { + "type": "string" + }, + "otherDomains": { + "type": "string" + }, + "primaryDomain": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "pushDir": { + "type": "boolean" + }, + "skipDNS": { + "type": "boolean" } } }, diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 1e3d3cac2..8c4a3a271 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -207,9 +207,12 @@ definitions: type: object dto.ChangeRedisPass: properties: + database: + type: string value: type: string required: + - database - value type: object dto.Clean: @@ -506,6 +509,7 @@ definitions: - image - volume - network + - buildcache type: string withTagAll: type: boolean @@ -2225,6 +2229,8 @@ definitions: properties: containerName: type: string + database: + type: string maxclients: type: string maxmemory: @@ -2237,6 +2243,8 @@ definitions: type: string timeout: type: string + required: + - database type: object dto.RedisConfPersistenceUpdate: properties: @@ -2244,6 +2252,8 @@ definitions: type: string appendonly: type: string + database: + type: string save: type: string type: @@ -2252,16 +2262,21 @@ definitions: - rbd type: string required: + - database - type type: object dto.RedisConfUpdate: properties: + database: + type: string maxclients: type: string maxmemory: type: string timeout: type: string + required: + - database type: object dto.RedisPersistence: properties: @@ -2269,13 +2284,19 @@ definitions: type: string appendonly: type: string + database: + type: string save: type: string + required: + - database type: object dto.RedisStatus: properties: connected_clients: type: string + database: + type: string instantaneous_ops_per_sec: type: string keyspace_hits: @@ -2300,6 +2321,8 @@ definitions: type: string used_memory_rss: type: string + required: + - database type: object dto.ResourceLimit: properties: @@ -3070,6 +3093,8 @@ definitions: type: string dir: type: string + disableCNAME: + type: boolean dnsAccount: $ref: '#/definitions/model.WebsiteDnsAccount' dnsAccountId: @@ -3084,6 +3109,10 @@ definitions: type: string message: type: string + nameserver1: + type: string + nameserver2: + type: string organization: type: string pem: @@ -3096,6 +3125,8 @@ definitions: type: string pushDir: type: boolean + skipDNS: + type: boolean startDate: type: string status: @@ -4422,7 +4453,6 @@ definitions: required: - id - match - - modifier - name - operate - proxyHost @@ -4446,7 +4476,11 @@ definitions: properties: ID: type: integer - SkipDNSCheck: + nameservers: + items: + type: string + type: array + skipDNSCheck: type: boolean required: - ID @@ -4463,12 +4497,18 @@ definitions: type: string dir: type: string + disableCNAME: + type: boolean dnsAccountId: type: integer id: type: integer keyType: type: string + nameserver1: + type: string + nameserver2: + type: string otherDomains: type: string primaryDomain: @@ -4477,6 +4517,8 @@ definitions: type: string pushDir: type: boolean + skipDNS: + type: boolean required: - acmeAccountId - primaryDomain @@ -4496,14 +4538,43 @@ definitions: type: object request.WebsiteSSLUpdate: properties: + acmeAccountId: + type: integer + apply: + type: boolean autoRenew: type: boolean description: type: string + dir: + type: string + disableCNAME: + type: boolean + dnsAccountId: + type: integer id: type: integer + keyType: + type: string + nameserver1: + type: string + nameserver2: + type: string + otherDomains: + type: string + primaryDomain: + type: string + provider: + type: string + pushDir: + type: boolean + skipDNS: + type: boolean required: + - acmeAccountId - id + - primaryDomain + - provider type: object request.WebsiteSSLUpload: properties: @@ -8277,31 +8348,18 @@ paths: summary: Page postgresql databases tags: - Database Postgresql - /databases/redis/backup/search: - post: + /databases/redis/conf: + get: consumes: - application/json - description: 获取 redis 备份记录分页 + description: 获取 redis 配置信息 parameters: - description: request in: body name: request required: true schema: - $ref: '#/definitions/dto.PageInfo' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page redis backups - tags: - - Database Redis - /databases/redis/conf: - get: - description: 获取 redis 配置信息 + $ref: '#/definitions/dto.OperationWithName' responses: "200": description: OK @@ -8366,7 +8424,16 @@ paths: paramKeys: [] /databases/redis/persistence/conf: get: + consumes: + - application/json description: 获取 redis 持久化配置 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperationWithName' responses: "200": description: OK @@ -8405,7 +8472,16 @@ paths: paramKeys: [] /databases/redis/status: get: + consumes: + - application/json description: 获取 redis 状态信息 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperationWithName' responses: "200": description: OK diff --git a/frontend/src/api/interface/database.ts b/frontend/src/api/interface/database.ts index b7dfd4af3..3bb23913d 100644 --- a/frontend/src/api/interface/database.ts +++ b/frontend/src/api/interface/database.ts @@ -221,20 +221,18 @@ export namespace Database { // redis export interface RedisConfUpdate { + database: string; timeout: string; maxclients: string; maxmemory: string; } export interface RedisConfPersistenceUpdate { + database: string; type: string; appendonly: string; appendfsync: string; save: string; } - export interface RedisConfUpdateByFile { - file: string; - restartNow: boolean; - } export interface RedisStatus { tcp_port: string; uptime_in_days: string; @@ -263,16 +261,6 @@ export namespace Database { appendfsync: string; save: string; } - export interface FileRecord { - fileName: string; - fileDir: string; - createdAt: string; - size: string; - } - export interface RedisRecover { - fileName: string; - fileDir: string; - } // remote export interface DatabaseInfo { diff --git a/frontend/src/api/modules/database.ts b/frontend/src/api/modules/database.ts index 70966c73d..5ffe19f9f 100644 --- a/frontend/src/api/modules/database.ts +++ b/frontend/src/api/modules/database.ts @@ -108,20 +108,20 @@ export const loadRemoteAccess = (type: string, database: string) => { }; // redis -export const loadRedisStatus = () => { - return http.get(`/databases/redis/status`); +export const loadRedisStatus = (database: string) => { + return http.post(`/databases/redis/status`, { name: database }); }; -export const loadRedisConf = () => { - return http.get(`/databases/redis/conf`); +export const loadRedisConf = (database: string) => { + return http.post(`/databases/redis/conf`, { name: database }); }; -export const redisPersistenceConf = () => { - return http.get(`/databases/redis/persistence/conf`); +export const redisPersistenceConf = (database: string) => { + return http.post(`/databases/redis/persistence/conf`, { name: database }); }; -export const changeRedisPassword = (value: string) => { - if (value) { - value = Base64.encode(value); +export const changeRedisPassword = (database: string, password: string) => { + if (password) { + password = Base64.encode(password); } - return http.post(`/databases/redis/password`, { value: value }); + return http.post(`/databases/redis/password`, { database: database, value: password }); }; export const updateRedisPersistenceConf = (params: Database.RedisConfPersistenceUpdate) => { return http.post(`/databases/redis/persistence/update`, params); @@ -129,7 +129,7 @@ export const updateRedisPersistenceConf = (params: Database.RedisConfPersistence export const updateRedisConf = (params: Database.RedisConfUpdate) => { return http.post(`/databases/redis/conf/update`, params); }; -export const updateRedisConfByFile = (params: Database.RedisConfUpdateByFile) => { +export const updateRedisConfByFile = (params: Database.DBConfUpdate) => { return http.post(`/databases/redis/conffile/update`, params); }; diff --git a/frontend/src/components/app-status/index.vue b/frontend/src/components/app-status/index.vue index 2c0fb88d4..92e9f03dd 100644 --- a/frontend/src/components/app-status/index.vue +++ b/frontend/src/components/app-status/index.vue @@ -167,7 +167,7 @@ let refresh = ref(1); const httpPort = ref(0); const httpsPort = ref(0); -const em = defineEmits(['setting', 'isExist', 'before', 'update:loading', 'update:maskShow']); +const em = defineEmits(['setting', 'isExist', 'before', 'after', 'update:loading', 'update:maskShow']); const setting = () => { em('setting', false); }; @@ -227,6 +227,7 @@ const onOperate = async (operation: string) => { em('update:loading', false); MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); onCheck(); + em('after'); }) .catch(() => { em('update:loading', false); diff --git a/frontend/src/components/terminal/index.vue b/frontend/src/components/terminal/index.vue index feb350943..4c088e989 100644 --- a/frontend/src/components/terminal/index.vue +++ b/frontend/src/components/terminal/index.vue @@ -176,12 +176,14 @@ const onWSReceive = (message: MessageEvent) => { switch (wsMsg.type) { case 'cmd': { term.value.element && term.value.focus(); - let receiveMsg = Base64.decode(wsMsg.data); - if (initCmd.value != '') { - receiveMsg = receiveMsg.replace(initCmd.value.trim(), '').trim(); - initCmd.value = ''; + if (wsMsg.data) { + let receiveMsg = Base64.decode(wsMsg.data); + if (initCmd.value != '') { + receiveMsg = receiveMsg?.replace(initCmd.value.trim(), '').trim(); + initCmd.value = ''; + } + term.value.write(receiveMsg); } - wsMsg.data && term.value.write(receiveMsg); break; } case 'heartbeat': { diff --git a/frontend/src/views/database/redis/index.vue b/frontend/src/views/database/redis/index.vue index 9dd86e5fd..b2e9a356e 100644 --- a/frontend/src/views/database/redis/index.vue +++ b/frontend/src/views/database/redis/index.vue @@ -1,16 +1,51 @@