Skip to content

Commit

Permalink
feat: Redis 支持远程数据库 (#5014)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssongliu committed May 15, 2024
1 parent c564359 commit 94cebfd
Show file tree
Hide file tree
Showing 23 changed files with 796 additions and 35 deletions.
25 changes: 22 additions & 3 deletions backend/app/api/v1/database_redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
// @Param request body dto.OperationWithName true "request"
// @Success 200 {object} dto.RedisStatus
// @Security ApiKeyAuth
// @Router /databases/redis/status [get]
// @Router /databases/redis/status [post]
func (b *BaseApi) LoadRedisStatus(c *gin.Context) {
var req dto.OperationWithName
if err := helper.CheckBind(&req, c); err != nil {
Expand All @@ -38,7 +38,7 @@ func (b *BaseApi) LoadRedisStatus(c *gin.Context) {
// @Param request body dto.OperationWithName true "request"
// @Success 200 {object} dto.RedisConf
// @Security ApiKeyAuth
// @Router /databases/redis/conf [get]
// @Router /databases/redis/conf [post]
func (b *BaseApi) LoadRedisConf(c *gin.Context) {
var req dto.OperationWithName
if err := helper.CheckBind(&req, c); err != nil {
Expand All @@ -60,7 +60,7 @@ func (b *BaseApi) LoadRedisConf(c *gin.Context) {
// @Param request body dto.OperationWithName true "request"
// @Success 200 {object} dto.RedisPersistence
// @Security ApiKeyAuth
// @Router /databases/redis/persistence/conf [get]
// @Router /databases/redis/persistence/conf [post]
func (b *BaseApi) LoadPersistenceConf(c *gin.Context) {
var req dto.OperationWithName
if err := helper.CheckBind(&req, c); err != nil {
Expand All @@ -75,6 +75,25 @@ func (b *BaseApi) LoadPersistenceConf(c *gin.Context) {
helper.SuccessWithData(c, data)
}

func (b *BaseApi) CheckHasCli(c *gin.Context) {
helper.SuccessWithData(c, redisService.CheckHasCli())
}

// @Tags Database Redis
// @Summary Install redis-cli
// @Description 安装 redis cli
// @Success 200
// @Security ApiKeyAuth
// @Router /databases/redis/install/cli [post]
func (b *BaseApi) InstallCli(c *gin.Context) {
if err := redisService.InstallCli(); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}

helper.SuccessWithOutData(c)
}

// @Tags Database Redis
// @Summary Update redis conf
// @Description 更新 redis 配置信息
Expand Down
36 changes: 26 additions & 10 deletions backend/app/api/v1/terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package v1
import (
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
Expand Down Expand Up @@ -88,23 +89,38 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) {
return
}
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
}

from := c.Query("from")
defer wsConn.Close()
commands := []string{"redis-cli"}
if len(redisInfo.Password) != 0 {
commands = []string{"redis-cli", "-a", redisInfo.Password, "--no-auth-warning"}
database, err := databaseService.Get(name)
if wshandleError(wsConn, errors.WithMessage(err, "no such database in db")) {
return
}
pidMap := loadMapFromDockerTop(redisInfo.Password)
itemCmds := append([]string{"exec", "-it", redisInfo.ContainerName}, commands...)
if from == "local" {
redisInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: name, Type: "redis"})
if wshandleError(wsConn, errors.WithMessage(err, "no such database in db")) {
return
}
name = redisInfo.ContainerName
if len(database.Password) != 0 {
commands = []string{"redis-cli", "-a", database.Password, "--no-auth-warning"}
}
} else {
itemPort := fmt.Sprintf("%v", database.Port)
commands = []string{"redis-cli", "-h", database.Address, "-p", itemPort}
if len(database.Password) != 0 {
commands = []string{"redis-cli", "-h", database.Address, "-p", itemPort, "-a", database.Password, "--no-auth-warning"}
}
name = "1Panel-redis-cli-tools"
}

pidMap := loadMapFromDockerTop(name)
itemCmds := append([]string{"exec", "-it", name}, commands...)
slave, err := terminal.NewCommand(itemCmds)
if wshandleError(wsConn, err) {
return
}
defer killBash(redisInfo.ContainerName, strings.Join(commands, " "), pidMap)
defer killBash(name, strings.Join(commands, " "), pidMap)
defer slave.Close()

tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
Expand Down
24 changes: 20 additions & 4 deletions backend/app/service/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import (
"path"

"github.com/1Panel-dev/1Panel/backend/utils/postgresql"
client2 "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client"
pg_client "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client"
redis_client "github.com/1Panel-dev/1Panel/backend/utils/redis"

"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/buserr"
Expand Down Expand Up @@ -113,7 +114,7 @@ func (u *DatabaseService) LoadItems(dbType string) ([]dto.DatabaseItem, error) {
func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool {
switch req.Type {
case constant.AppPostgresql:
_, err := postgresql.NewPostgresqlClient(client2.DBInfo{
_, err := postgresql.NewPostgresqlClient(pg_client.DBInfo{
From: "remote",
Address: req.Address,
Port: req.Port,
Expand All @@ -122,6 +123,13 @@ func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool {
Timeout: 6,
})
return err == nil
case constant.AppRedis:
_, err := redis_client.NewRedisClient(redis_client.DBInfo{
Address: req.Address,
Port: req.Port,
Password: req.Password,
})
return err == nil
case "mysql", "mariadb":
_, err := mysql.NewMysqlClient(client.DBInfo{
From: "remote",
Expand Down Expand Up @@ -153,7 +161,7 @@ func (u *DatabaseService) Create(req dto.DatabaseCreate) error {
}
switch req.Type {
case constant.AppPostgresql:
if _, err := postgresql.NewPostgresqlClient(client2.DBInfo{
if _, err := postgresql.NewPostgresqlClient(pg_client.DBInfo{
From: "remote",
Address: req.Address,
Port: req.Port,
Expand All @@ -163,6 +171,14 @@ func (u *DatabaseService) Create(req dto.DatabaseCreate) error {
}); err != nil {
return err
}
case constant.AppRedis:
if _, err := redis_client.NewRedisClient(redis_client.DBInfo{
Address: req.Address,
Port: req.Port,
Password: req.Password,
}); err != nil {
return err
}
case "mysql", "mariadb":
if _, err := mysql.NewMysqlClient(client.DBInfo{
From: "remote",
Expand Down Expand Up @@ -249,7 +265,7 @@ func (u *DatabaseService) Delete(req dto.DatabaseDelete) error {
func (u *DatabaseService) Update(req dto.DatabaseUpdate) error {
switch req.Type {
case constant.AppPostgresql:
if _, err := postgresql.NewPostgresqlClient(client2.DBInfo{
if _, err := postgresql.NewPostgresqlClient(pg_client.DBInfo{
From: "remote",
Address: req.Address,
Port: req.Port,
Expand Down
33 changes: 33 additions & 0 deletions backend/app/service/database_redis.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package service

import (
"context"
"encoding/json"
"errors"
"fmt"
Expand All @@ -11,6 +12,8 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/compose"
"github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/docker/docker/api/types/container"
_ "github.com/go-sql-driver/mysql"
)

Expand All @@ -24,6 +27,9 @@ type IRedisService interface {
LoadStatus(req dto.OperationWithName) (*dto.RedisStatus, error)
LoadConf(req dto.OperationWithName) (*dto.RedisConf, error)
LoadPersistenceConf(req dto.OperationWithName) (*dto.RedisPersistence, error)

CheckHasCli() bool
InstallCli() error
}

func NewIRedisService() IRedisService {
Expand All @@ -50,6 +56,33 @@ func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error {
return nil
}

func (u *RedisService) CheckHasCli() bool {
client, err := docker.NewDockerClient()
if err != nil {
return false
}
defer client.Close()
containerLists, err := client.ContainerList(context.Background(), container.ListOptions{})
if err != nil {
return false
}
for _, item := range containerLists {
if strings.ReplaceAll(item.Names[0], "/", "") == "1Panel-redis-cli-tools" {
return true
}
}
return false
}

func (u *RedisService) InstallCli() error {
item := dto.ContainerOperate{
Name: "1Panel-redis-cli-tools",
Image: "redis:7.2.4",
Network: "1panel-network",
}
return NewIContainerService().ContainerCreate(item)
}

func (u *RedisService) ChangePassword(req dto.ChangeRedisPass) error {
if err := updateInstallInfoInDB("redis", req.Database, "password", req.Value); err != nil {
return err
Expand Down
2 changes: 2 additions & 0 deletions backend/router/ro_database.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) {
cmdRouter.POST("/redis/status", baseApi.LoadRedisStatus)
cmdRouter.POST("/redis/conf", baseApi.LoadRedisConf)
cmdRouter.GET("/redis/exec", baseApi.RedisWsSsh)
cmdRouter.GET("/redis/check", baseApi.CheckHasCli)
cmdRouter.POST("/redis/install/cli", baseApi.InstallCli)
cmdRouter.POST("/redis/password", baseApi.ChangeRedisPassword)
cmdRouter.POST("/redis/conf/update", baseApi.UpdateRedisConf)
cmdRouter.POST("/redis/persistence/update", baseApi.UpdateRedisPersistenceConf)
Expand Down
26 changes: 26 additions & 0 deletions backend/utils/redis/redis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package redis

import (
"fmt"

"github.com/go-redis/redis"
)

type DBInfo struct {
Address string `json:"address"`
Port uint `json:"port"`
Password string `json:"password"`
}

func NewRedisClient(conn DBInfo) (*redis.Client, error) {
client := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%v", conn.Address, conn.Port),
Password: conn.Password,
DB: 0,
})

if _, err := client.Ping().Result(); err != nil {
return client, err
}
return client, nil
}
25 changes: 22 additions & 3 deletions cmd/server/docs/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 22 additions & 3 deletions cmd/server/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -5103,7 +5103,7 @@
}
},
"/databases/redis/conf": {
"get": {
"post": {
"security": [
{
"ApiKeyAuth": []
Expand Down Expand Up @@ -5178,6 +5178,25 @@
}
}
},
"/databases/redis/install/cli": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "安装 redis cli",
"tags": [
"Database Redis"
],
"summary": "Install redis-cli",
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/databases/redis/password": {
"post": {
"security": [
Expand Down Expand Up @@ -5219,7 +5238,7 @@
}
},
"/databases/redis/persistence/conf": {
"get": {
"post": {
"security": [
{
"ApiKeyAuth": []
Expand Down Expand Up @@ -5295,7 +5314,7 @@
}
},
"/databases/redis/status": {
"get": {
"post": {
"security": [
{
"ApiKeyAuth": []
Expand Down
Loading

0 comments on commit 94cebfd

Please sign in to comment.