testing a 2nd remote with mshell --server

This commit is contained in:
sawka
2022-08-17 12:24:09 -07:00
parent f86de49e31
commit 249bf88a4d
7 changed files with 198 additions and 29 deletions
+5
View File
@@ -451,6 +451,11 @@ func main() {
fmt.Printf("[error] ensuring local remote: %v\n", err)
return
}
err = sstore.AddTest01Remote(context.Background())
if err != nil {
fmt.Printf("[error] ensuring test01 remote: %v\n", err)
return
}
_, err = sstore.EnsureDefaultSession(context.Background())
if err != nil {
fmt.Printf("[error] ensuring default session: %v\n", err)
+21 -3
View File
@@ -1,17 +1,28 @@
CREATE TABLE schema_migrations (version uint64,dirty bool);
CREATE UNIQUE INDEX version_unique ON schema_migrations (version);
CREATE TABLE client (
userid varchar(36) NOT NULL,
userpublickeybytes blob NOT NULL,
userprivatekeybytes blob NOT NULL
);
CREATE TABLE session (
sessionid varchar(36) PRIMARY KEY,
name varchar(50) NOT NULL,
sessionidx int NOT NULL,
activescreenid varchar(36) NOT NULL,
notifynum int NOT NULL
notifynum int NOT NULL,
owneruserid varchar(36) NOT NULL,
sharemode varchar(12) NOT NULL,
accesskey varchar(36) NOT NULL
);
CREATE TABLE window (
sessionid varchar(36) NOT NULL,
windowid varchar(36) NOT NULL,
curremote varchar(50) NOT NULL,
winopts json NOT NULL,
owneruserid varchar(36) NOT NULL,
sharemode varchar(12) NOT NULL,
shareopts json NOT NULL,
PRIMARY KEY (sessionid, windowid)
);
CREATE TABLE screen (
@@ -21,6 +32,8 @@ CREATE TABLE screen (
activewindowid varchar(36) NOT NULL,
screenidx int NOT NULL,
screenopts json NOT NULL,
owneruserid varchar(36) NOT NULL,
sharemode varchar(12) NOT NULL,
PRIMARY KEY (sessionid, screenid)
);
CREATE TABLE screen_window (
@@ -43,7 +56,7 @@ CREATE TABLE remote_instance (
CREATE TABLE line (
sessionid varchar(36) NOT NULL,
windowid varchar(36) NOT NULL,
lineid int NOT NULL,
lineid varchar(36) NOT NULL,
userid varchar(36) NOT NULL,
ts bigint NOT NULL,
linetype varchar(10) NOT NULL,
@@ -53,8 +66,13 @@ CREATE TABLE line (
);
CREATE TABLE remote (
remoteid varchar(36) PRIMARY KEY,
physicalid varchar(36) NOT NULL,
remotetype varchar(10) NOT NULL,
remotename varchar(50) NOT NULL,
remotealias varchar(50) NOT NULL,
remotecanonicalname varchar(200) NOT NULL,
remotesudo boolean NOT NULL,
remoteuser varchar(50) NOT NULL,
remotehost varchar(200) NOT NULL,
autoconnect boolean NOT NULL,
initpk json NOT NULL,
sshopts json NOT NULL,
+63 -8
View File
@@ -88,6 +88,9 @@ func HandleCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
case "cd":
return CdCommand(ctx, pk)
case "cr":
return CrCommand(ctx, pk)
case "compgen":
return CompGenCommand(ctx, pk)
@@ -189,8 +192,8 @@ func resolveScreenId(ctx context.Context, pk *scpacket.FeCommandPacketType, sess
return resolveSessionScreen(ctx, sessionId, screenArg)
}
func resolveRemote(ctx context.Context, pk *scpacket.FeCommandPacketType, sessionId string, windowId string) (string, string, *sstore.RemoteState, error) {
remoteName := pk.Kwargs["remote"]
// returns (remoteName, remoteId, state, err)
func resolveRemote(ctx context.Context, remoteName string, sessionId string, windowId string) (string, string, *sstore.RemoteState, error) {
if remoteName == "" {
return "", "", nil, nil
}
@@ -242,7 +245,7 @@ func resolveIds(ctx context.Context, pk *scpacket.FeCommandPacketType, rtype int
}
}
if (rtype&R_Remote)+(rtype&R_RemoteOpt) > 0 {
rtn.RemoteName, rtn.RemoteId, rtn.RemoteState, err = resolveRemote(ctx, pk, rtn.SessionId, rtn.WindowId)
rtn.RemoteName, rtn.RemoteId, rtn.RemoteState, err = resolveRemote(ctx, pk.Kwargs["remote"], rtn.SessionId, rtn.WindowId)
if err != nil {
return rtn, err
}
@@ -332,6 +335,9 @@ func evalCommandInternal(ctx context.Context, pk *scpacket.FeCommandPacketType)
if commandStr == "cd" || strings.HasPrefix(commandStr, "cd ") {
metaCmd = "cd"
commandStr = strings.TrimSpace(commandStr[2:])
} else if commandStr == "cr" || strings.HasPrefix(commandStr, "cr ") {
metaCmd = "cr"
commandStr = strings.TrimSpace(commandStr[2:])
} else if commandStr[0] == '/' {
spaceIdx := strings.Index(commandStr, " ")
if spaceIdx == -1 {
@@ -419,14 +425,67 @@ func ScreenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
return update, nil
}
func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveIds(ctx, pk, R_Session|R_Window)
if err != nil {
return nil, fmt.Errorf("/cr error: %w", err)
}
newRemote := firstArg(pk)
if newRemote == "" {
return nil, nil
}
remoteName, remoteId, _, err := resolveRemote(ctx, newRemote, ids.SessionId, ids.WindowId)
fmt.Printf("found: name[%s] id[%s] err[%v]\n", remoteName, remoteId, err)
if err != nil {
return nil, err
}
if remoteId == "" {
return nil, fmt.Errorf("/cr error: remote not found")
}
err = sstore.UpdateCurRemote(ctx, ids.SessionId, ids.WindowId, remoteName)
if err != nil {
return nil, fmt.Errorf("/cr error: cannot update curremote: %w", err)
}
update := sstore.WindowUpdate{
Window: sstore.WindowType{
SessionId: ids.SessionId,
WindowId: ids.WindowId,
CurRemote: remoteName,
},
Info: &sstore.InfoMsgType{
InfoMsg: fmt.Sprintf("current remote = %s", remoteName),
TimeoutMs: 2000,
},
}
return update, nil
}
func CdCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveIds(ctx, pk, R_Session|R_Window|R_Remote)
if err != nil {
return nil, fmt.Errorf("/cd error: %w", err)
}
newDir := firstArg(pk)
curRemote := remote.GetRemoteById(ids.RemoteId)
if curRemote == nil {
return nil, fmt.Errorf("invalid remote, cannot change directory")
}
if !curRemote.IsConnected() {
return nil, fmt.Errorf("remote is not connected, cannot change directory")
}
if newDir == "" {
return nil, nil
if ids.RemoteState == nil {
return nil, fmt.Errorf("remote state is not available")
}
return sstore.InfoUpdate{
Info: &sstore.InfoMsgType{
InfoMsg: fmt.Sprintf("[%s] current directory = %s", ids.RemoteName, ids.RemoteState.Cwd),
},
}, nil
}
newDir, err = curRemote.ExpandHomeDir(newDir)
if err != nil {
return nil, err
}
if !strings.HasPrefix(newDir, "/") {
if ids.RemoteState == nil {
@@ -442,10 +501,6 @@ func CdCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.Up
cdPacket := packet.MakeCdPacket()
cdPacket.ReqId = uuid.New().String()
cdPacket.Dir = newDir
curRemote := remote.GetRemoteById(ids.RemoteId)
if curRemote == nil {
return nil, fmt.Errorf("invalid remote, cannot execute command")
}
resp, err := curRemote.PacketRpc(ctx, cdPacket)
if err != nil {
return nil, err
+45 -8
View File
@@ -5,7 +5,8 @@ import (
"encoding/base64"
"errors"
"fmt"
"os/exec"
"path"
"strings"
"sync"
"github.com/scripthaus-dev/mshell/pkg/base"
@@ -19,6 +20,17 @@ const DefaultTermRows = 25
const DefaultTermCols = 80
const DefaultTerm = "xterm-256color"
const MShellServerCommand = `
PATH=$PATH:~/.mshell;
which mshell > /dev/null;
if [[ "$?" -ne 0 ]]
then
printf "\n##N{\"type\": \"init\", \"notfound\": true, \"uname\": \"%s | %s\"}\n" "$(uname -s)" "$(uname -m)"
else
mshell --server
fi
`
const (
StatusInit = "init"
StatusConnected = "connected"
@@ -154,17 +166,23 @@ func MakeMShell(r *sstore.RemoteType) *MShellProc {
return rtn
}
func convertSSHOpts(opts *sstore.SSHOpts) shexec.SSHOpts {
if opts == nil {
return shexec.SSHOpts{}
}
return shexec.SSHOpts{
SSHHost: opts.SSHHost,
SSHOptsStr: opts.SSHOptsStr,
SSHIdentity: opts.SSHIdentity,
SSHUser: opts.SSHUser,
}
}
func (msh *MShellProc) Launch() {
msh.Lock.Lock()
defer msh.Lock.Unlock()
msPath, err := base.GetMShellPath()
if err != nil {
msh.Status = StatusError
msh.Err = err
return
}
ecmd := exec.Command(msPath, "--server")
ecmd := convertSSHOpts(msh.Remote.SSHOpts).MakeSSHExecCmd(MShellServerCommand)
cproc, err := shexec.MakeClientProc(ecmd)
if err != nil {
msh.Status = StatusError
@@ -203,6 +221,25 @@ func (msh *MShellProc) GetDefaultState() *sstore.RemoteState {
return &sstore.RemoteState{Cwd: msh.ServerProc.InitPk.HomeDir}
}
func (msh *MShellProc) ExpandHomeDir(pathStr string) (string, error) {
if pathStr != "~" && !strings.HasPrefix(pathStr, "~/") {
return pathStr, nil
}
msh.Lock.Lock()
defer msh.Lock.Unlock()
if msh.ServerProc.InitPk == nil {
return "", fmt.Errorf("remote not connected, does not have home directory set for ~ expansion")
}
homeDir := msh.ServerProc.InitPk.HomeDir
if homeDir == "" {
return "", fmt.Errorf("remote does not have HOME set, cannot do ~ expansion")
}
if pathStr == "~" {
return homeDir, nil
}
return path.Join(homeDir, pathStr[2:]), nil
}
func (msh *MShellProc) IsCmdRunning(ck base.CommandKey) bool {
msh.Lock.Lock()
defer msh.Lock.Unlock()
+27
View File
@@ -40,6 +40,20 @@ func GetAllRemotes(ctx context.Context) ([]*RemoteType, error) {
return rtn, nil
}
func GetRemoteByAlias(ctx context.Context, alias string) (*RemoteType, error) {
var remote *RemoteType
err := WithTx(ctx, func(tx *TxWrap) error {
query := `SELECT * FROM remote WHERE remotealias = ?`
m := tx.GetMap(query, alias)
remote = RemoteFromMap(m)
return nil
})
if err != nil {
return nil, err
}
return remote, nil
}
func GetRemoteById(ctx context.Context, remoteId string) (*RemoteType, error) {
var remote *RemoteType
err := WithTx(ctx, func(tx *TxWrap) error {
@@ -573,3 +587,16 @@ func UpdateRemoteCwd(ctx context.Context, rname string, sessionId string, window
})
return &ri, txErr
}
func UpdateCurRemote(ctx context.Context, sessionId string, windowId string, remoteName string) error {
txErr := WithTx(ctx, func(tx *TxWrap) error {
query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?`
if !tx.Exists(query, sessionId, windowId) {
return fmt.Errorf("cannot update curremote, no window found")
}
query = `UPDATE window SET curremote = ? WHERE sessionid = ? AND windowid = ?`
tx.ExecWrap(query, remoteName, sessionId, windowId)
return nil
})
return txErr
}
+37 -5
View File
@@ -432,13 +432,13 @@ func AddCmdLine(ctx context.Context, sessionId string, windowId string, userId s
}
func EnsureLocalRemote(ctx context.Context) error {
remoteId, err := base.GetRemoteId()
physicalId, err := base.GetRemoteId()
if err != nil {
return fmt.Errorf("getting local remoteid: %w", err)
return fmt.Errorf("getting local physical remoteid: %w", err)
}
remote, err := GetRemoteById(ctx, remoteId)
remote, err := GetRemoteByPhysicalId(ctx, physicalId)
if err != nil {
return fmt.Errorf("getting remote[%s] from db: %w", remoteId, err)
return fmt.Errorf("getting remote[%s] from db: %w", physicalId, err)
}
if remote != nil {
return nil
@@ -453,7 +453,8 @@ func EnsureLocalRemote(ctx context.Context) error {
}
// create the local remote
localRemote := &RemoteType{
RemoteId: remoteId,
RemoteId: uuid.New().String(),
PhysicalId: physicalId,
RemoteType: "ssh",
RemoteAlias: LocalRemoteName,
RemoteCanonicalName: fmt.Sprintf("%s@%s", user.Username, hostName),
@@ -470,6 +471,37 @@ func EnsureLocalRemote(ctx context.Context) error {
return nil
}
func AddTest01Remote(ctx context.Context) error {
remote, err := GetRemoteByAlias(ctx, "test01")
if err != nil {
return fmt.Errorf("getting remote[test01] from db: %w", err)
}
if remote != nil {
return nil
}
testRemote := &RemoteType{
RemoteId: uuid.New().String(),
RemoteType: "ssh",
RemoteAlias: "test01",
RemoteCanonicalName: "ubuntu@test01.ec2",
RemoteSudo: false,
RemoteUser: "ubuntu",
RemoteHost: "test01.ec2",
SSHOpts: &SSHOpts{
SSHHost: "test01.ec2",
SSHUser: "ubuntu",
SSHIdentity: "/Users/mike/aws/mfmt.pem",
},
AutoConnect: true,
}
err = InsertRemote(ctx, testRemote)
if err != nil {
return err
}
log.Printf("[db] added remote '%s', id=%s\n", testRemote.GetName(), testRemote.RemoteId)
return nil
}
func EnsureDefaultSession(ctx context.Context) (*SessionType, error) {
session, err := GetSessionByName(ctx, DefaultSessionName)
if err != nil {
-5
View File
@@ -16,11 +16,6 @@ type UpdatePacket interface {
UpdateType() string
}
type UpdateCmd struct {
CmdId string
Status string
}
type PtyDataUpdate struct {
SessionId string `json:"sessionid"`
CmdId string `json:"cmdid"`