-
Notifications
You must be signed in to change notification settings - Fork 3.2k
feat: Change the local connection mode of the terminal #8409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,55 @@ import ( | |
| "github.com/pkg/errors" | ||
| ) | ||
|
|
||
| func (b *BaseApi) WsSSH(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.Base.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 | ||
| } | ||
| name, err := loadExecutor() | ||
| if wshandleError(wsConn, err) { | ||
| return | ||
| } | ||
| slave, err := terminal.NewCommand(name) | ||
| if wshandleError(wsConn, err) { | ||
| return | ||
| } | ||
| 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 (b *BaseApi) ContainerWsSSH(c *gin.Context) { | ||
| wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil) | ||
| if err != nil { | ||
|
|
@@ -42,7 +91,7 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) { | |
| } | ||
| source := c.Query("source") | ||
| var containerID string | ||
| var initCmd string | ||
| var initCmd []string | ||
| switch source { | ||
| case "redis": | ||
| containerID, initCmd, err = loadRedisInitCmd(c) | ||
|
|
@@ -59,11 +108,11 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) { | |
| return | ||
| } | ||
| pidMap := loadMapFromDockerTop(containerID) | ||
| slave, err := terminal.NewCommand("clear && " + initCmd) | ||
| slave, err := terminal.NewCommand("docker", initCmd...) | ||
| if wshandleError(wsConn, err) { | ||
| return | ||
| } | ||
| defer killBash(containerID, strings.ReplaceAll(initCmd, fmt.Sprintf("docker exec -it %s ", containerID), ""), pidMap) | ||
| defer killBash(containerID, strings.ReplaceAll(strings.Join(initCmd, " "), fmt.Sprintf("exec -it %s ", containerID), ""), pidMap) | ||
| defer slave.Close() | ||
|
|
||
| tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false) | ||
|
|
@@ -83,62 +132,63 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) { | |
| } | ||
| } | ||
|
|
||
| func loadRedisInitCmd(c *gin.Context) (string, string, error) { | ||
| func loadRedisInitCmd(c *gin.Context) (string, []string, error) { | ||
| name := c.Query("name") | ||
| from := c.Query("from") | ||
| commands := "redis-cli" | ||
| commands := []string{"exec", "-it"} | ||
| database, err := databaseService.Get(name) | ||
| if err != nil { | ||
| return "", "", fmt.Errorf("no such database in db, err: %v", err) | ||
| return "", nil, fmt.Errorf("no such database in db, err: %v", err) | ||
| } | ||
| if from == "local" { | ||
| redisInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: name, Type: "redis"}) | ||
| if err != nil { | ||
| return "", "", fmt.Errorf("no such app in db, err: %v", err) | ||
| return "", nil, fmt.Errorf("no such app in db, err: %v", err) | ||
| } | ||
| name = redisInfo.ContainerName | ||
| commands = append(commands, []string{name, "redis-cli"}...) | ||
| if len(database.Password) != 0 { | ||
| commands = "redis-cli -a " + database.Password + " --no-auth-warning" | ||
| commands = append(commands, []string{"-a", database.Password, "--no-auth-warning"}...) | ||
| } | ||
| } else { | ||
| commands = fmt.Sprintf("redis-cli -h %s -p %v", database.Address, database.Port) | ||
| name = "1Panel-redis-cli-tools" | ||
| commands = append(commands, []string{name, "redis-cli", "-h", database.Address, "-p", fmt.Sprintf("%v", database.Port)}...) | ||
| if len(database.Password) != 0 { | ||
| commands = fmt.Sprintf("redis-cli -h %s -p %v -a %s --no-auth-warning", database.Address, database.Port, database.Password) | ||
| commands = append(commands, []string{"-a", database.Password, "--no-auth-warning"}...) | ||
| } | ||
| name = "1Panel-redis-cli-tools" | ||
| } | ||
| return name, fmt.Sprintf("docker exec -it %s %s", name, commands), nil | ||
| return name, commands, nil | ||
| } | ||
|
|
||
| func loadOllamaInitCmd(c *gin.Context) (string, string, error) { | ||
| func loadOllamaInitCmd(c *gin.Context) (string, []string, error) { | ||
| name := c.Query("name") | ||
| if cmd.CheckIllegal(name) { | ||
| return "", "", fmt.Errorf("ollama model %s contains illegal characters", name) | ||
| return "", nil, fmt.Errorf("ollama model %s contains illegal characters", name) | ||
| } | ||
| ollamaInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: "", Type: "ollama"}) | ||
| if err != nil { | ||
| return "", "", fmt.Errorf("no such app in db, err: %v", err) | ||
| return "", nil, 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 | ||
| return containerName, []string{"exec", "-it", containerName, "ollama", "run", name}, nil | ||
| } | ||
|
|
||
| func loadContainerInitCmd(c *gin.Context) (string, string, error) { | ||
| func loadContainerInitCmd(c *gin.Context) (string, []string, error) { | ||
| containerID := c.Query("containerid") | ||
| command := c.Query("command") | ||
| user := c.Query("user") | ||
| if cmd.CheckIllegal(user, containerID, command) { | ||
| return "", "", fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID) | ||
| return "", nil, fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID) | ||
| } | ||
| if len(command) == 0 || len(containerID) == 0 { | ||
| return "", "", fmt.Errorf("error param of command: %s or containerID: %s", command, containerID) | ||
| return "", nil, fmt.Errorf("error param of command: %s or containerID: %s", command, containerID) | ||
| } | ||
| command = fmt.Sprintf("docker exec -it %s %s", containerID, command) | ||
| commands := []string{"exec", "-it", containerID, command} | ||
| if len(user) != 0 { | ||
| command = fmt.Sprintf("docker exec -it -u %s %s %s", user, containerID, command) | ||
| commands = []string{"exec", "-it", "-u", user, containerID, command} | ||
| } | ||
|
|
||
| return containerID, command, nil | ||
| return containerID, commands, nil | ||
| } | ||
|
|
||
| func wshandleError(ws *websocket.Conn, err error) bool { | ||
|
|
@@ -204,3 +254,12 @@ var upGrader = websocket.Upgrader{ | |
| return true | ||
| }, | ||
| } | ||
|
|
||
| func loadExecutor() (string, error) { | ||
| std, err := cmd.RunDefaultWithStdoutBashC("echo $SHELL") | ||
| if err != nil { | ||
| return "", fmt.Errorf("load default executor failed, err: %s", std) | ||
| } | ||
|
|
||
| return strings.ReplaceAll(std, "\n", ""), nil | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code Differences and Analysis:1. Added Function
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks generally clean and well-structured. However, there are a few improvements that can be made for readability and maintainability:
Variable Naming: Some variable names could be more descriptive to improve clarity.
Error Handling: The
wshandleErrorfunction should log an error message in addition to returning true. This will help with debugging if something goes wrong later on.Concurrency Consideration: The way processes like containers and terminals are managed is relatively straightforward but consider how concurrent access might impact performance or behavior.
Comments: Adding comments about certain logic decisions would make it easier for others (or future you) to understand the purpose of different parts of the code.
Updated Code
Key Changes:
int,string).wssHandleErrorfunction, including calling it twice: once with additional log messages and again directly.loadExecutor()return value by checking which shell works first before proceeding with fallback.close(quitChannel)for proper channel closure and added comments for better understanding.