From 4d075e32bf256f10052d97b0d2fd73f14b51730a Mon Sep 17 00:00:00 2001 From: sawka Date: Sun, 2 Oct 2022 18:52:55 -0700 Subject: [PATCH] updateremote (non-visual) --- pkg/cmdrunner/cmdrunner.go | 63 +++++++++++++++++++++++++++++++++++--- pkg/remote/remote.go | 15 +++++++++ pkg/sstore/dbops.go | 58 +++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 5 deletions(-) diff --git a/pkg/cmdrunner/cmdrunner.go b/pkg/cmdrunner/cmdrunner.go index ab44bb0b..37fa0eea 100644 --- a/pkg/cmdrunner/cmdrunner.go +++ b/pkg/cmdrunner/cmdrunner.go @@ -91,6 +91,7 @@ func init() { registerCmdFn("remote:new", RemoteNewCommand) registerCmdFn("remote:archive", RemoteArchiveCommand) registerCmdFn("remote:set", RemoteSetCommand) + registerCmdAlias("remote:edit", RemoteSetCommand) registerCmdFn("remote:disconnect", RemoteDisconnectCommand) registerCmdFn("remote:connect", RemoteConnectCommand) registerCmdFn("remote:install", RemoteInstallCommand) @@ -537,6 +538,7 @@ type RemoteEditArgs struct { SSHPassword string SSHKeyFile string Color string + EditMap map[string]interface{} } func parseRemoteEditArgs(isNew bool, pk *scpacket.FeCommandPacketType) (*RemoteEditArgs, error) { @@ -591,11 +593,14 @@ func parseRemoteEditArgs(isNew bool, pk *scpacket.FeCommandPacketType) (*RemoteE return nil, fmt.Errorf("invalid alias format") } } - connectMode := sstore.ConnectModeAuto + var connectMode string + if isNew { + connectMode = sstore.ConnectModeAuto + } if pk.Kwargs["connectmode"] != "" { connectMode = pk.Kwargs["connectmode"] } - if !sstore.IsValidConnectMode(connectMode) { + if connectMode != "" && !sstore.IsValidConnectMode(connectMode) { err := fmt.Errorf("invalid connectmode %q: valid modes are %s", connectMode, formatStrs([]string{sstore.ConnectModeStartup, sstore.ConnectModeAuto, sstore.ConnectModeManual}, "or", false)) return nil, err } @@ -616,6 +621,28 @@ func parseRemoteEditArgs(isNew bool, pk *scpacket.FeCommandPacketType) (*RemoteE sshOpts.SSHIdentity = keyFile sshOpts.SSHPassword = sshPassword } + + // set up editmap + editMap := make(map[string]interface{}) + if _, found := pk.Kwargs[sstore.RemoteField_Alias]; found { + editMap[sstore.RemoteField_Alias] = alias + } + if connectMode != "" { + editMap[sstore.RemoteField_ConnectMode] = connectMode + } + if _, found := pk.Kwargs[sstore.RemoteField_AutoInstall]; found { + editMap[sstore.RemoteField_AutoInstall] = autoInstall + } + if _, found := pk.Kwargs["key"]; found { + editMap[sstore.RemoteField_SSHKey] = keyFile + } + if _, found := pk.Kwargs[sstore.RemoteField_Color]; found { + editMap[sstore.RemoteField_Color] = color + } + if _, found := pk.Kwargs["password"]; found { + editMap[sstore.RemoteField_SSHPassword] = sshPassword + } + return &RemoteEditArgs{ SSHOpts: sshOpts, Sudo: isSudo, @@ -626,6 +653,7 @@ func parseRemoteEditArgs(isNew bool, pk *scpacket.FeCommandPacketType) (*RemoteE SSHKeyFile: keyFile, SSHPassword: sshPassword, Color: color, + EditMap: editMap, }, nil } @@ -676,12 +704,37 @@ func RemoteNewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss } func RemoteSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { - ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_Remote) + ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote) if err != nil { return nil, err } - fmt.Printf("ids: %v\n", ids) - return nil, nil + visualEdit := resolveBool(pk.Kwargs["visual"], false) + isSubmitted := resolveBool(pk.Kwargs["submit"], false) + editArgs, err := parseRemoteEditArgs(false, pk) + if err != nil { + return makeRemoteEditErrorReturn(visualEdit, fmt.Errorf("/remote:new %v", err)) + } + if visualEdit && !isSubmitted && len(editArgs.EditMap) == 0 { + return sstore.ModelUpdate{ + Info: &sstore.InfoMsgType{ + RemoteEdit: &sstore.RemoteEditType{ + RemoteEdit: true, + RemoteId: ids.Remote.RemotePtr.RemoteId, + }, + }, + }, nil + } + err = ids.Remote.MShell.UpdateRemote(ctx, editArgs.EditMap) + if err != nil { + return makeRemoteEditErrorReturn(visualEdit, fmt.Errorf("/remote:new error updating remote: %v", err)) + } + update := sstore.ModelUpdate{ + Info: &sstore.InfoMsgType{ + InfoMsg: fmt.Sprintf("remote %q updated", ids.Remote.DisplayName), + TimeoutMs: 2000, + }, + } + return update, nil } func RemoteShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index f5e56fce..25005379 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -584,6 +584,21 @@ func (msh *MShellProc) GetNumRunningCommands() int { return len(msh.RunningCmds) } +func (msh *MShellProc) UpdateRemote(ctx context.Context, editMap map[string]interface{}) error { + msh.Lock.Lock() + defer msh.Lock.Unlock() + updatedRemote, err := sstore.UpdateRemote(ctx, msh.Remote.RemoteId, editMap) + if err != nil { + return err + } + if updatedRemote == nil { + return fmt.Errorf("no remote returned from UpdateRemote") + } + msh.Remote = updatedRemote + go msh.NotifyRemoteUpdate() + return nil +} + func (msh *MShellProc) Disconnect(force bool) { status := msh.GetStatus() if status != StatusConnected && status != StatusConnecting { diff --git a/pkg/sstore/dbops.go b/pkg/sstore/dbops.go index f3c7cff6..27d59bdb 100644 --- a/pkg/sstore/dbops.go +++ b/pkg/sstore/dbops.go @@ -1031,3 +1031,61 @@ func GetSessionStats(ctx context.Context, sessionId string) (*SessionStatsType, rtn.DiskStats = diskSize return rtn, nil } + +const ( + RemoteField_Alias = "alias" // string + RemoteField_ConnectMode = "connectmode" // string + RemoteField_AutoInstall = "autoinstall" // bool + RemoteField_SSHKey = "sshkey" // string + RemoteField_SSHPassword = "sshpassword" // string + RemoteField_Color = "color" // string +) + +// editMap: alias, connectmode, autoinstall, sshkey, color, sshpassword (from constants) +func UpdateRemote(ctx context.Context, remoteId string, editMap map[string]interface{}) (*RemoteType, error) { + var rtn *RemoteType + txErr := WithTx(ctx, func(tx *TxWrap) error { + query := `SELECT remoteid FROM remote WHERE remoteid = ?` + if !tx.Exists(query, remoteId) { + return fmt.Errorf("remote not found") + } + if alias, found := editMap[RemoteField_Alias]; found { + query = `SELECT remoteid FROM remote WHERE remotealias = ? AND remoteid <> ?` + if tx.Exists(query, alias, remoteId) { + return fmt.Errorf("remote has duplicate alias, cannot update") + } + query = `UPDATE remote SET remotealias = ? WHERE remoteid = ?` + tx.ExecWrap(query, alias, remoteId) + } + if mode, found := editMap[RemoteField_ConnectMode]; found { + query = `UPDATE remote SET connectmode = ? WHERE remoteid = ?` + tx.ExecWrap(query, mode, remoteId) + } + if autoInstall, found := editMap[RemoteField_AutoInstall]; found { + query = `UPDATE remote SET autoinstall = ? WHERE remoteid = ?` + tx.ExecWrap(query, autoInstall, remoteId) + } + if sshKey, found := editMap[RemoteField_SSHKey]; found { + query = `UPDATE remote SET sshopts = json_set(sshopts, '$.sshidentity', ?) WHERE remoteid = ?` + tx.ExecWrap(query, sshKey, remoteId) + } + if sshPassword, found := editMap[RemoteField_SSHPassword]; found { + query = `UPDATE remote SET sshopts = json_set(sshopts, '$.sshpassword', ?) WHERE remoteid = ?` + tx.ExecWrap(query, sshPassword, remoteId) + } + if color, found := editMap[RemoteField_Color]; found { + query = `UPDATE remote SET remoteopts = json_set(remoteopts, '$.color', ?) WHERE remoteid = ?` + tx.ExecWrap(query, color, remoteId) + } + var err error + rtn, err = GetRemoteById(tx.Context(), remoteId) + if err != nil { + return err + } + return nil + }) + if txErr != nil { + return nil, txErr + } + return rtn, nil +}