From d143ca282017f344ae3a44f7bf7830d10de95edd Mon Sep 17 00:00:00 2001 From: sawka Date: Mon, 26 Sep 2022 21:09:43 -0700 Subject: [PATCH] working on /remote:install --- pkg/cmdrunner/cmdrunner.go | 5 +++ pkg/remote/remote.go | 82 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/pkg/cmdrunner/cmdrunner.go b/pkg/cmdrunner/cmdrunner.go index b4405b68..e3106585 100644 --- a/pkg/cmdrunner/cmdrunner.go +++ b/pkg/cmdrunner/cmdrunner.go @@ -93,6 +93,7 @@ func init() { registerCmdFn("remote:set", RemoteSetCommand) registerCmdFn("remote:disconnect", RemoteDisconnectCommand) registerCmdFn("remote:connect", RemoteConnectCommand) + registerCmdFn("remote:install", RemoteInstallCommand) registerCmdFn("window:resize", WindowResizeCommand) @@ -414,6 +415,10 @@ func UnSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore return update, nil } +func RemoteInstallCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { + return nil, nil +} + func RemoteConnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote) if err != nil { diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index dbc3b513..d9e46236 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -38,17 +38,21 @@ const PtyReadBufSize = 100 const MShellVersion = "v0.1.0" const MShellVersionConstraint = "^0.1" -const MShellServerCommand = ` +const MShellServerCommandFmt = ` PATH=$PATH:~/.mshell; -which mshell > /dev/null; +which mshell-[%VERSION%] > /dev/null; if [[ "$?" -ne 0 ]] then printf "\n##N{\"type\": \"init\", \"notfound\": true, \"uname\": \"%s | %s\"}\n" "$(uname -s)" "$(uname -m)" else - mshell --server + mshell-[%VERSION%] --server fi ` +func MakeServerCommandStr() string { + return strings.ReplaceAll(MShellServerCommandFmt, "[%VERSION%]", semver.MajorMinor(base.MShellVersion)) +} + const ( StatusInit = "init" StatusConnected = "connected" @@ -83,7 +87,12 @@ type MShellProc struct { ControllingPty *os.File PtyBuffer *circbuf.Buffer MakeClientCancelFn context.CancelFunc + + // install + InstallStatus string NeedsMShellUpgrade bool + InstallCancelFn context.CancelFunc + InstallErr error RunningCmds []base.CommandKey } @@ -116,6 +125,12 @@ func (msh *MShellProc) GetStatus() string { return msh.Status } +func (msh *MShellProc) GetInstallStatus() string { + msh.Lock.Lock() + defer msh.Lock.Unlock() + return msh.InstallStatus +} + func (state RemoteRuntimeState) GetBaseDisplayName() string { if state.RemoteAlias != "" { return state.RemoteAlias @@ -528,6 +543,14 @@ func (msh *MShellProc) setErrorStatus(err error) { go msh.NotifyRemoteUpdate() } +func (msh *MShellProc) setInstallErrorStatus(err error) { + msh.Lock.Lock() + defer msh.Lock.Unlock() + msh.InstallStatus = StatusError + msh.InstallErr = err + go msh.NotifyRemoteUpdate() +} + func (msh *MShellProc) GetRemoteCopy() sstore.RemoteType { msh.Lock.Lock() defer msh.Lock.Unlock() @@ -626,6 +649,56 @@ func (msh *MShellProc) RunPtyReadLoop(cmdPty *os.File) { } } +func (msh *MShellProc) RunInstall() { + remoteCopy := msh.GetRemoteCopy() + if remoteCopy.Archived { + msh.WriteToPtyBuffer("cannot install on archived remote\n") + return + } + curStatus := msh.GetInstallStatus() + if curStatus == StatusConnecting { + msh.WriteToPtyBuffer("cannot install on remote that is already trying to install, cancel current install to try again") + return + } + msh.WriteToPtyBuffer("installing mshell %s to %s...\n", MShellVersion, remoteCopy.RemoteCanonicalName) + sshOpts := convertSSHOpts(remoteCopy.SSHOpts) + sshOpts.SSHErrorsToTty = true + cmdStr := shexec.MakeInstallCommandStr() + ecmd := sshOpts.MakeSSHExecCmd(cmdStr) + cmdPty, err := msh.addControllingTty(ecmd) + if err != nil { + statusErr := fmt.Errorf("cannot attach controlling tty to mshell install command: %w", err) + msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error()) + msh.setInstallErrorStatus(statusErr) + return + } + defer func() { + if len(ecmd.ExtraFiles) > 0 { + ecmd.ExtraFiles[len(ecmd.ExtraFiles)-1].Close() + } + }() + go msh.RunPtyReadLoop(cmdPty) + clientCtx, clientCancelFn := context.WithCancel(context.Background()) + defer clientCancelFn() + msh.WithLock(func() { + msh.InstallStatus = StatusConnecting + msh.InstallCancelFn = clientCancelFn + go msh.NotifyRemoteUpdate() + }) + msgFn := func(msg string) { + msh.WriteToPtyBuffer("%s", msg) + } + err = shexec.RunInstallFromCmd(clientCtx, ecmd, true, "", msgFn) + if err != nil { + statusErr := fmt.Errorf("install failed: %w", err) + msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error()) + msh.setInstallErrorStatus(statusErr) + return + } + msh.WriteToPtyBuffer("successfully installed mshell %s\n", MShellVersion) + return +} + func (msh *MShellProc) Launch() { remoteCopy := msh.GetRemoteCopy() if remoteCopy.Archived { @@ -640,7 +713,8 @@ func (msh *MShellProc) Launch() { msh.WriteToPtyBuffer("connecting to %s...\n", remoteCopy.RemoteCanonicalName) sshOpts := convertSSHOpts(remoteCopy.SSHOpts) sshOpts.SSHErrorsToTty = true - ecmd := sshOpts.MakeSSHExecCmd(MShellServerCommand) + cmdStr := MakeServerCommandStr() + ecmd := sshOpts.MakeSSHExecCmd(cmdStr) cmdPty, err := msh.addControllingTty(ecmd) if err != nil { statusErr := fmt.Errorf("cannot attach controlling tty to mshell command: %w", err)