mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-01 02:54:43 +08:00
fix(container): Fix cpu surge when the container terminal executes exit (#8096)
Some checks failed
SonarCloud Scan / SonarCloud (push) Failing after -19s
Some checks failed
SonarCloud Scan / SonarCloud (push) Failing after -19s
Refs #7574
This commit is contained in:
parent
766beae4e1
commit
402b41100b
19 changed files with 92 additions and 256 deletions
|
@ -10,7 +10,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/service"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/copier"
|
||||
|
@ -74,7 +73,7 @@ func (b *BaseApi) WsSsh(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (b *BaseApi) RedisWsSsh(c *gin.Context) {
|
||||
func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
|
||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
||||
|
@ -96,193 +95,105 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) {
|
|||
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
|
||||
return
|
||||
}
|
||||
source := c.Query("source")
|
||||
var containerID string
|
||||
var initCmd string
|
||||
switch source {
|
||||
case "redis":
|
||||
containerID, initCmd, err = loadRedisInitCmd(c)
|
||||
case "ollama":
|
||||
containerID, initCmd, err = loadOllamaInitCmd(c)
|
||||
case "container":
|
||||
containerID, initCmd, err = loadContainerInitCmd(c)
|
||||
default:
|
||||
if wshandleError(wsConn, fmt.Errorf("not support such source %s", source)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
pidMap := loadMapFromDockerTop(containerID)
|
||||
slave, err := terminal.NewCommand("clear && " + initCmd)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer killBash(containerID, strings.ReplaceAll(initCmd, fmt.Sprintf("docker exec -it %s ", containerID), ""), pidMap)
|
||||
defer slave.Close()
|
||||
|
||||
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
|
||||
quitChan := make(chan bool, 3)
|
||||
tty.Start(quitChan)
|
||||
go slave.Wait(quitChan)
|
||||
|
||||
<-quitChan
|
||||
|
||||
global.LOG.Info("websocket finished")
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func loadRedisInitCmd(c *gin.Context) (string, string, error) {
|
||||
name := c.Query("name")
|
||||
from := c.Query("from")
|
||||
commands := []string{"redis-cli"}
|
||||
commands := "redis-cli"
|
||||
database, err := databaseService.Get(name)
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "no such database in db")) {
|
||||
return
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("no such database in db, err: %v", err)
|
||||
}
|
||||
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
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("no such app in db, err: %v", err)
|
||||
}
|
||||
name = redisInfo.ContainerName
|
||||
if len(database.Password) != 0 {
|
||||
commands = []string{"redis-cli", "-a", database.Password, "--no-auth-warning"}
|
||||
commands = "redis-cli -a " + database.Password + " --no-auth-warning"
|
||||
}
|
||||
} else {
|
||||
itemPort := fmt.Sprintf("%v", database.Port)
|
||||
commands = []string{"redis-cli", "-h", database.Address, "-p", itemPort}
|
||||
commands = fmt.Sprintf("redis-cli -h %s -p %v", database.Address, database.Port)
|
||||
if len(database.Password) != 0 {
|
||||
commands = []string{"redis-cli", "-h", database.Address, "-p", itemPort, "-a", database.Password, "--no-auth-warning"}
|
||||
commands = fmt.Sprintf("redis-cli -h %s -p %v -a %s --no-auth-warning", database.Address, database.Port, database.Password)
|
||||
}
|
||||
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(name, strings.Join(commands, " "), pidMap)
|
||||
defer slave.Close()
|
||||
|
||||
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
|
||||
quitChan := make(chan bool, 3)
|
||||
tty.Start(quitChan)
|
||||
go slave.Wait(quitChan)
|
||||
|
||||
<-quitChan
|
||||
|
||||
global.LOG.Info("websocket finished")
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
return name, fmt.Sprintf("docker exec -it %s %s", name, commands), nil
|
||||
}
|
||||
|
||||
func (b *BaseApi) OllamaWsSsh(c *gin.Context) {
|
||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
defer wsConn.Close()
|
||||
|
||||
if global.CONF.System.IsDemo {
|
||||
if wshandleError(wsConn, errors.New(" demo server, prohibit this operation!")) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "invalid param cols in request")) {
|
||||
return
|
||||
}
|
||||
rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
|
||||
return
|
||||
}
|
||||
func loadOllamaInitCmd(c *gin.Context) (string, string, error) {
|
||||
name := c.Query("name")
|
||||
if cmd.CheckIllegal(name) {
|
||||
if wshandleError(wsConn, errors.New(" The command contains illegal characters.")) {
|
||||
return
|
||||
}
|
||||
return "", "", fmt.Errorf("ollama model %s contains illegal characters", name)
|
||||
}
|
||||
container, err := service.LoadContainerName()
|
||||
if wshandleError(wsConn, errors.WithMessage(err, " load container name for ollama failed")) {
|
||||
return
|
||||
}
|
||||
commands := []string{"ollama", "run", name}
|
||||
|
||||
pidMap := loadMapFromDockerTop(container)
|
||||
fmt.Println("pidMap")
|
||||
for k, v := range pidMap {
|
||||
fmt.Println(k, v)
|
||||
}
|
||||
itemCmds := append([]string{"exec", "-it", container}, commands...)
|
||||
slave, err := terminal.NewCommand(itemCmds)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer killBash(container, strings.Join(commands, " "), pidMap)
|
||||
defer slave.Close()
|
||||
|
||||
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
|
||||
quitChan := make(chan bool, 3)
|
||||
tty.Start(quitChan)
|
||||
go slave.Wait(quitChan)
|
||||
|
||||
<-quitChan
|
||||
|
||||
global.LOG.Info("websocket finished")
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
ollamaInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: "", Type: "ollama"})
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("no such app in db, err: %v", err)
|
||||
}
|
||||
containerName := ollamaInfo.ContainerName
|
||||
return containerName, fmt.Sprintf("docker exec -it %s ollama run %s", containerName, name), nil
|
||||
}
|
||||
|
||||
func (b *BaseApi) ContainerWsSsh(c *gin.Context) {
|
||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
defer wsConn.Close()
|
||||
|
||||
if global.CONF.System.IsDemo {
|
||||
if wshandleError(wsConn, errors.New(" demo server, prohibit this operation!")) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func loadContainerInitCmd(c *gin.Context) (string, string, error) {
|
||||
containerID := c.Query("containerid")
|
||||
command := c.Query("command")
|
||||
user := c.Query("user")
|
||||
if len(command) == 0 || len(containerID) == 0 {
|
||||
if wshandleError(wsConn, errors.New("error param of command or containerID")) {
|
||||
return
|
||||
}
|
||||
}
|
||||
cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "invalid param cols in request")) {
|
||||
return
|
||||
}
|
||||
rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
|
||||
return
|
||||
}
|
||||
|
||||
cmds := []string{"exec", containerID, command}
|
||||
if len(user) != 0 {
|
||||
cmds = []string{"exec", "-u", user, containerID, command}
|
||||
}
|
||||
if cmd.CheckIllegal(user, containerID, command) {
|
||||
if wshandleError(wsConn, errors.New(" The command contains illegal characters.")) {
|
||||
return
|
||||
}
|
||||
return "", "", fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID)
|
||||
}
|
||||
stdout, err := cmd.ExecWithCheck("docker", cmds...)
|
||||
if wshandleError(wsConn, errors.WithMessage(err, stdout)) {
|
||||
return
|
||||
if len(command) == 0 || len(containerID) == 0 {
|
||||
return "", "", fmt.Errorf("error param of command: %s or containerID: %s", command, containerID)
|
||||
}
|
||||
|
||||
commands := []string{"exec", "-it", containerID, command}
|
||||
command = fmt.Sprintf("docker exec -it %s %s", containerID, command)
|
||||
if len(user) != 0 {
|
||||
commands = []string{"exec", "-it", "-u", user, containerID, command}
|
||||
}
|
||||
pidMap := loadMapFromDockerTop(containerID)
|
||||
slave, err := terminal.NewCommand(commands)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer killBash(containerID, command, pidMap)
|
||||
defer slave.Close()
|
||||
|
||||
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, true)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
command = fmt.Sprintf("docker exec -it -u %s %s %s", user, containerID, command)
|
||||
}
|
||||
|
||||
quitChan := make(chan bool, 3)
|
||||
tty.Start(quitChan)
|
||||
go slave.Wait(quitChan)
|
||||
|
||||
<-quitChan
|
||||
|
||||
global.LOG.Info("websocket finished")
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
return containerID, command, nil
|
||||
}
|
||||
|
||||
func wshandleError(ws *websocket.Conn, err error) bool {
|
||||
|
|
|
@ -15,7 +15,6 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) {
|
|||
|
||||
baseApi := v1.ApiGroupApp.BaseApi
|
||||
{
|
||||
aiToolsRouter.GET("/ollama/exec", baseApi.OllamaWsSsh)
|
||||
aiToolsRouter.POST("/ollama/close", baseApi.CloseOllamaModel)
|
||||
aiToolsRouter.POST("/ollama/model", baseApi.CreateOllamaModel)
|
||||
aiToolsRouter.POST("/ollama/model/recreate", baseApi.RecreateOllamaModel)
|
||||
|
|
|
@ -15,7 +15,7 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
|
|||
Use(middleware.PasswordExpired())
|
||||
baseApi := v1.ApiGroupApp.BaseApi
|
||||
{
|
||||
baRouter.GET("/exec", baseApi.ContainerWsSsh)
|
||||
baRouter.GET("/exec", baseApi.ContainerWsSSH)
|
||||
baRouter.GET("/stats/:id", baseApi.ContainerStats)
|
||||
|
||||
baRouter.POST("", baseApi.ContainerCreate)
|
||||
|
|
|
@ -38,7 +38,6 @@ func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) {
|
|||
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.GET("/redis/check", baseApi.CheckHasCli)
|
||||
cmdRouter.POST("/redis/install/cli", baseApi.InstallCli)
|
||||
cmdRouter.POST("/redis/password", baseApi.ChangeRedisPassword)
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
|
@ -82,58 +79,6 @@ func (c *ConnInfo) Close() {
|
|||
_ = c.Client.Close()
|
||||
}
|
||||
|
||||
type SshConn struct {
|
||||
StdinPipe io.WriteCloser
|
||||
ComboOutput *wsBufferWriter
|
||||
Session *gossh.Session
|
||||
}
|
||||
|
||||
func (c *ConnInfo) NewSshConn(cols, rows int) (*SshConn, error) {
|
||||
sshSession, err := c.Client.NewSession()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stdinP, err := sshSession.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
comboWriter := new(wsBufferWriter)
|
||||
sshSession.Stdout = comboWriter
|
||||
sshSession.Stderr = comboWriter
|
||||
|
||||
modes := gossh.TerminalModes{
|
||||
gossh.ECHO: 1,
|
||||
gossh.TTY_OP_ISPEED: 14400,
|
||||
gossh.TTY_OP_OSPEED: 14400,
|
||||
}
|
||||
if err := sshSession.RequestPty("xterm", rows, cols, modes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := sshSession.Shell(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SshConn{StdinPipe: stdinP, ComboOutput: comboWriter, Session: sshSession}, nil
|
||||
}
|
||||
|
||||
func (s *SshConn) Close() {
|
||||
if s.Session != nil {
|
||||
s.Session.Close()
|
||||
}
|
||||
}
|
||||
|
||||
type wsBufferWriter struct {
|
||||
buffer bytes.Buffer
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (w *wsBufferWriter) Write(p []byte) (int, error) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
return w.buffer.Write(p)
|
||||
}
|
||||
|
||||
func makePrivateKeySigner(privateKey []byte, passPhrase []byte) (gossh.Signer, error) {
|
||||
if len(passPhrase) != 0 {
|
||||
return gossh.ParsePrivateKeyWithPassphrase(privateKey, passPhrase)
|
||||
|
|
|
@ -25,14 +25,24 @@ type LocalCommand struct {
|
|||
pty *os.File
|
||||
}
|
||||
|
||||
func NewCommand(commands []string) (*LocalCommand, error) {
|
||||
cmd := exec.Command("docker", commands...)
|
||||
func NewCommand(initCmd string) (*LocalCommand, error) {
|
||||
cmd := exec.Command("bash")
|
||||
if term := os.Getenv("TERM"); term != "" {
|
||||
cmd.Env = append(os.Environ(), "TERM="+term)
|
||||
} else {
|
||||
cmd.Env = append(os.Environ(), "TERM=xterm")
|
||||
}
|
||||
|
||||
pty, err := pty.Start(cmd)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to start command")
|
||||
}
|
||||
|
||||
if len(initCmd) != 0 {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
_, _ = pty.Write([]byte(initCmd + "\n"))
|
||||
}
|
||||
|
||||
lcmd := &LocalCommand{
|
||||
closeSignal: DefaultCloseSignal,
|
||||
closeTimeout: DefaultCloseTimeout,
|
||||
|
|
|
@ -123,8 +123,6 @@ const message = {
|
|||
},
|
||||
msg: {
|
||||
noneData: 'No data available',
|
||||
disConn:
|
||||
'Please click the disconnect button directly to terminate the terminal connection, avoiding the use of exit commands like {0}.',
|
||||
delete: `This operation delete can't be undone. Do you want to continue?`,
|
||||
clean: `This operation clean can't be undone. Do you want to continue?`,
|
||||
deleteTitle: 'Delete',
|
||||
|
|
|
@ -122,8 +122,6 @@ const message = {
|
|||
},
|
||||
msg: {
|
||||
noneData: '利用可能なデータはありません',
|
||||
disConn:
|
||||
'端末接続を切断するには、{0} のような終了コマンドを使用せずに、直接切断ボタンをクリックしてください',
|
||||
delete: `この操作削除は元に戻すことはできません。続けたいですか?`,
|
||||
clean: `この操作は取り消すことはできません。続けたいですか?`,
|
||||
deleteTitle: '消去',
|
||||
|
|
|
@ -123,8 +123,6 @@ const message = {
|
|||
},
|
||||
msg: {
|
||||
noneData: '데이터가 없습니다',
|
||||
disConn:
|
||||
'종료 명령어인 {0} 등을 사용하지 않고 직접 연결 끊기 버튼을 클릭하여 터미널 연결을 종료해 주십시오.',
|
||||
delete: `이 작업은 되돌릴 수 없습니다. 계속하시겠습니까?`,
|
||||
clean: `이 작업은 되돌릴 수 없습니다. 계속하시겠습니까?`,
|
||||
deleteTitle: '삭제',
|
||||
|
|
|
@ -123,8 +123,6 @@ const message = {
|
|||
},
|
||||
msg: {
|
||||
noneData: 'Tiada data tersedia',
|
||||
disConn:
|
||||
'Sila klik butang putus sambungan secara langsung untuk menamatkan sambungan terminal, mengelakkan penggunaan arahan keluar seperti {0}.',
|
||||
delete: 'Operasi ini tidak boleh diundur. Adakah anda mahu meneruskan?',
|
||||
clean: 'Operasi ini tidak boleh diundur. Adakah anda mahu meneruskan?',
|
||||
deleteTitle: 'Padam',
|
||||
|
|
|
@ -123,8 +123,6 @@ const message = {
|
|||
},
|
||||
msg: {
|
||||
noneData: 'Nenhum dado disponível',
|
||||
disConn:
|
||||
'Por favor, clique diretamente no botão de desconexão para encerrar a conexão do terminal, evitando o uso de comandos de saída como {0}.',
|
||||
delete: 'Esta operação de exclusão não pode ser desfeita. Deseja continuar?',
|
||||
clean: 'Esta operação de limpeza não pode ser desfeita. Deseja continuar?',
|
||||
deleteTitle: 'Excluir',
|
||||
|
|
|
@ -124,8 +124,6 @@ const message = {
|
|||
},
|
||||
msg: {
|
||||
noneData: 'Нет данных',
|
||||
disConn:
|
||||
'Пожалуйста, нажмите кнопку отключения, чтобы разорвать соединение с терминалом, избегая использования команд выхода, таких как {0}.',
|
||||
delete: 'Эта операция удаления не может быть отменена. Хотите продолжить?',
|
||||
clean: 'Эта операция очистки не может быть отменена. Хотите продолжить?',
|
||||
deleteTitle: 'Удалить',
|
||||
|
|
|
@ -123,7 +123,6 @@ const message = {
|
|||
},
|
||||
msg: {
|
||||
noneData: '暫無資料',
|
||||
disConn: '請直接點選斷開按鈕斷開終端連接,避免使用 {0} 等退出指令。',
|
||||
delete: '刪除 操作不可復原,是否繼續?',
|
||||
clean: '清空 操作不可復原,是否繼續?',
|
||||
deleteTitle: '刪除',
|
||||
|
|
|
@ -121,7 +121,6 @@ const message = {
|
|||
Rollbacking: '快照回滚中,请稍候...',
|
||||
},
|
||||
msg: {
|
||||
disConn: '请直接点击断开按钮断开终端连接,避免使用 {0} 等退出命令',
|
||||
noneData: '暂无数据',
|
||||
delete: '删除 操作不可回滚,是否继续?',
|
||||
clean: '清空 操作不可回滚,是否继续?',
|
||||
|
|
|
@ -16,12 +16,7 @@
|
|||
</template>
|
||||
</DrawerHeader>
|
||||
</template>
|
||||
<el-alert type="error" :closable="false">
|
||||
<template #title>
|
||||
<span>{{ $t('commons.msg.disConn', ['/bye exit']) }}</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
<Terminal class="mt-2" style="height: calc(100vh - 225px)" ref="terminalRef"></Terminal>
|
||||
<Terminal class="mt-2" style="height: calc(100vh - 175px)" ref="terminalRef"></Terminal>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
|
@ -67,8 +62,8 @@ const loadTooltip = () => {
|
|||
const initTerm = () => {
|
||||
nextTick(() => {
|
||||
terminalRef.value.acceptParams({
|
||||
endpoint: '/api/v1/ai/ollama/exec',
|
||||
args: `name=${itemName.value}`,
|
||||
endpoint: '/api/v1/containers/exec',
|
||||
args: `source=ollama&name=${itemName.value}`,
|
||||
error: '',
|
||||
initCmd: '',
|
||||
});
|
||||
|
|
|
@ -10,12 +10,7 @@
|
|||
<template #header>
|
||||
<DrawerHeader :header="$t('container.containerTerminal')" :resource="title" :back="handleClose" />
|
||||
</template>
|
||||
<el-alert type="error" :closable="false">
|
||||
<template #title>
|
||||
<span>{{ $t('commons.msg.disConn', ['exit']) }}</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
<el-form ref="formRef" class="mt-2" :model="form" label-position="top">
|
||||
<el-form ref="formRef" :model="form" label-position="top">
|
||||
<el-form-item :label="$t('commons.table.user')" prop="user">
|
||||
<el-input placeholder="root" clearable v-model="form.user" />
|
||||
</el-form-item>
|
||||
|
@ -51,7 +46,7 @@
|
|||
</el-button>
|
||||
<el-button v-else @click="onClose()">{{ $t('commons.button.disconnect') }}</el-button>
|
||||
<Terminal
|
||||
style="height: calc(100vh - 355px); margin-top: 18px"
|
||||
style="height: calc(100vh - 312px); margin-top: 18px"
|
||||
ref="terminalRef"
|
||||
v-if="terminalOpen"
|
||||
></Terminal>
|
||||
|
@ -104,7 +99,7 @@ const initTerm = (formEl: FormInstance | undefined) => {
|
|||
await nextTick();
|
||||
terminalRef.value!.acceptParams({
|
||||
endpoint: '/api/v1/containers/exec',
|
||||
args: `containerid=${form.containerID}&user=${form.user}&command=${form.command}`,
|
||||
args: `source=container&containerid=${form.containerID}&user=${form.user}&command=${form.command}`,
|
||||
error: '',
|
||||
initCmd: '',
|
||||
});
|
||||
|
|
|
@ -309,8 +309,8 @@ const initTerminal = async () => {
|
|||
terminalShow.value = true;
|
||||
redisStatus.value = 'Running';
|
||||
terminalRef.value.acceptParams({
|
||||
endpoint: '/api/v1/databases/redis/exec',
|
||||
args: `name=${currentDBName.value}&from=${currentDB.value.from}`,
|
||||
endpoint: '/api/v1/containers/exec',
|
||||
args: `source=redis&name=${currentDBName.value}&from=${currentDB.value.from}`,
|
||||
error: '',
|
||||
initCmd: '',
|
||||
});
|
||||
|
@ -327,8 +327,8 @@ const initTerminal = async () => {
|
|||
if (res.data.status === 'Running') {
|
||||
terminalShow.value = true;
|
||||
terminalRef.value.acceptParams({
|
||||
endpoint: '/api/v1/databases/redis/exec',
|
||||
args: `name=${currentDBName.value}&from=${currentDB.value.from}`,
|
||||
endpoint: '/api/v1/containers/exec',
|
||||
args: `source=redis&name=${currentDBName.value}&from=${currentDB.value.from}`,
|
||||
error: '',
|
||||
initCmd: '',
|
||||
});
|
||||
|
|
3
go.mod
3
go.mod
|
@ -58,6 +58,7 @@ require (
|
|||
golang.org/x/sys v0.29.0
|
||||
golang.org/x/term v0.28.0
|
||||
golang.org/x/text v0.21.0
|
||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/gorm v1.25.7
|
||||
|
@ -218,7 +219,6 @@ require (
|
|||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/testify v1.10.0 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cloudapp v1.0.1105 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1105 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1065 // indirect
|
||||
github.com/therootcompany/xz v1.0.1 // indirect
|
||||
|
@ -259,7 +259,6 @@ require (
|
|||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/time v0.8.0 // indirect
|
||||
golang.org/x/tools v0.28.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
|
||||
google.golang.org/grpc v1.67.1 // indirect
|
||||
|
|
3
go.sum
3
go.sum
|
@ -960,10 +960,7 @@ github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+z
|
|||
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
|
||||
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
|
||||
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cloudapp v1.0.1105 h1:ikgsQkFcKDzOJFbxIcSCdu7oj8GQBfwJohBpYHWeSco=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cloudapp v1.0.1105/go.mod h1:/GMcTQRH1+iDTX8RSl+G79doAWcabhpt+xmv3V9P3p0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1065 h1:krcqtAmexnHHBm/4ge4tr2b1cn/a7JGBESVGoZYXQAE=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1065/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1105 h1:lCs0dmezU6/8JcfNwEaam1Pm1RS/5MhXvNhf/X2y65s=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1105/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
|
|
Loading…
Add table
Reference in a new issue