mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
feat: first pass at sftp installer for waveshell
This does not completely work yet. In particular, you must attempt to connect to the client before attempting an install. It also does not work for auto installation yet.
This commit is contained in:
parent
e2e71898c1
commit
038471c394
34
go.work.sum
34
go.work.sum
@ -1,11 +1,45 @@
|
|||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
|
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/wavetermdev/ssh_config v0.0.0-20240109090616-36c8da3d7376 h1:tFhJgTu7lgd+hldLfPSzDCoWUpXI8wHKR3rxq5jTLkQ=
|
github.com/wavetermdev/ssh_config v0.0.0-20240109090616-36c8da3d7376 h1:tFhJgTu7lgd+hldLfPSzDCoWUpXI8wHKR3rxq5jTLkQ=
|
||||||
github.com/wavetermdev/ssh_config v0.0.0-20240109090616-36c8da3d7376/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
|
github.com/wavetermdev/ssh_config v0.0.0-20240109090616-36c8da3d7376/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
@ -60,6 +60,18 @@ func (cw CmdWrap) Start() error {
|
|||||||
return cw.Cmd.Start()
|
return cw.Cmd.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cw CmdWrap) StdinPipe() (io.WriteCloser, error) {
|
||||||
|
return cw.Cmd.StdinPipe()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw CmdWrap) StdoutPipe() (io.ReadCloser, error) {
|
||||||
|
return cw.Cmd.StdoutPipe()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw CmdWrap) StderrPipe() (io.ReadCloser, error) {
|
||||||
|
return cw.Cmd.StderrPipe()
|
||||||
|
}
|
||||||
|
|
||||||
type SessionWrap struct {
|
type SessionWrap struct {
|
||||||
Session *ssh.Session
|
Session *ssh.Session
|
||||||
StartCmd string
|
StartCmd string
|
||||||
@ -101,12 +113,35 @@ func (sw SessionWrap) Parser() (*packet.PacketParser, io.ReadCloser, io.ReadClos
|
|||||||
return packetParser, io.NopCloser(stdoutReader), io.NopCloser(stderrReader), nil
|
return packetParser, io.NopCloser(stdoutReader), io.NopCloser(stderrReader), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sw SessionWrap) StdinPipe() (io.WriteCloser, error) {
|
||||||
|
return sw.Session.StdinPipe()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sw SessionWrap) StdoutPipe() (io.ReadCloser, error) {
|
||||||
|
outPipe, err := sw.Session.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return io.NopCloser(outPipe), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sw SessionWrap) StderrPipe() (io.ReadCloser, error) {
|
||||||
|
errPipe, err := sw.Session.StderrPipe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return io.NopCloser(errPipe), nil
|
||||||
|
}
|
||||||
|
|
||||||
type ConnInterface interface {
|
type ConnInterface interface {
|
||||||
Kill()
|
Kill()
|
||||||
Wait() error
|
Wait() error
|
||||||
Sender() (*packet.PacketSender, io.WriteCloser, error)
|
Sender() (*packet.PacketSender, io.WriteCloser, error)
|
||||||
Parser() (*packet.PacketParser, io.ReadCloser, io.ReadCloser, error)
|
Parser() (*packet.PacketParser, io.ReadCloser, io.ReadCloser, error)
|
||||||
Start() error
|
Start() error
|
||||||
|
StdinPipe() (io.WriteCloser, error)
|
||||||
|
StdoutPipe() (io.ReadCloser, error)
|
||||||
|
StderrPipe() (io.ReadCloser, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientProc struct {
|
type ClientProc struct {
|
||||||
@ -175,6 +210,53 @@ func MakeClientProc(ctx context.Context, ecmd ConnInterface) (*ClientProc, *pack
|
|||||||
return cproc, cproc.InitPk, nil
|
return cproc, cproc.InitPk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MakeInstallProc(ctx context.Context, ecmd ConnInterface) (*ClientProc, *packet.InitPacketType, error) {
|
||||||
|
startTs := time.Now()
|
||||||
|
sender, inputWriter, err := ecmd.Sender()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
packetParser, stdoutReader, stderrReader, err := ecmd.Parser()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
err = ecmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("running local client: %w", err)
|
||||||
|
}
|
||||||
|
cproc := &ClientProc{
|
||||||
|
Cmd: ecmd,
|
||||||
|
StartTs: startTs,
|
||||||
|
StdinWriter: inputWriter,
|
||||||
|
StdoutReader: stdoutReader,
|
||||||
|
StderrReader: stderrReader,
|
||||||
|
Input: sender,
|
||||||
|
Output: packetParser,
|
||||||
|
}
|
||||||
|
|
||||||
|
var pk packet.PacketType
|
||||||
|
select {
|
||||||
|
case pk = <-packetParser.MainCh:
|
||||||
|
case <-ctx.Done():
|
||||||
|
cproc.Close()
|
||||||
|
return nil, nil, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
if pk != nil {
|
||||||
|
if pk.GetType() != packet.InitPacketStr {
|
||||||
|
cproc.Close()
|
||||||
|
return nil, nil, fmt.Errorf("invalid packet received from mshell client: %s", packet.AsString(pk))
|
||||||
|
}
|
||||||
|
initPk := pk.(*packet.InitPacketType)
|
||||||
|
cproc.InitPk = initPk
|
||||||
|
}
|
||||||
|
if cproc.InitPk == nil {
|
||||||
|
cproc.Close()
|
||||||
|
return nil, nil, fmt.Errorf("no init packet received from mshell client")
|
||||||
|
}
|
||||||
|
return cproc, cproc.InitPk, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cproc *ClientProc) Close() {
|
func (cproc *ClientProc) Close() {
|
||||||
if cproc.Input != nil {
|
if cproc.Input != nil {
|
||||||
cproc.Input.Close()
|
cproc.Input.Close()
|
||||||
|
@ -6,13 +6,14 @@ require (
|
|||||||
github.com/alessio/shellescape v1.4.1
|
github.com/alessio/shellescape v1.4.1
|
||||||
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
|
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
|
||||||
github.com/creack/pty v1.1.18
|
github.com/creack/pty v1.1.18
|
||||||
github.com/kevinburke/ssh_config v1.2.0
|
|
||||||
github.com/golang-migrate/migrate/v4 v4.16.2
|
github.com/golang-migrate/migrate/v4 v4.16.2
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/jmoiron/sqlx v1.3.5
|
github.com/jmoiron/sqlx v1.3.5
|
||||||
|
github.com/kevinburke/ssh_config v1.2.0
|
||||||
github.com/mattn/go-sqlite3 v1.14.16
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
|
github.com/pkg/sftp v1.13.6
|
||||||
github.com/sashabaranov/go-openai v1.9.0
|
github.com/sashabaranov/go-openai v1.9.0
|
||||||
github.com/sawka/txwrap v0.1.2
|
github.com/sawka/txwrap v0.1.2
|
||||||
github.com/wavetermdev/waveterm/waveshell v0.0.0
|
github.com/wavetermdev/waveterm/waveshell v0.0.0
|
||||||
@ -26,8 +27,10 @@ require (
|
|||||||
github.com/google/go-github/v57 v57.0.0 // indirect
|
github.com/google/go-github/v57 v57.0.0 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/kr/fs v0.1.0 // indirect
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/wavetermdev/waveterm/waveshell => ../waveshell
|
replace github.com/wavetermdev/waveterm/waveshell => ../waveshell
|
||||||
|
|
||||||
replace github.com/kevinburke/ssh_config => github.com/wavetermdev/ssh_config v0.0.0-20240109090616-36c8da3d7376
|
replace github.com/kevinburke/ssh_config => github.com/wavetermdev/ssh_config v0.0.0-20240109090616-36c8da3d7376
|
||||||
|
@ -29,6 +29,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
|
|||||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
||||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
||||||
|
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||||
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
@ -36,6 +38,8 @@ github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
|
|||||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
|
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||||
|
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY=
|
github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY=
|
||||||
@ -44,21 +48,56 @@ github.com/sashabaranov/go-openai v1.9.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOg
|
|||||||
github.com/sawka/txwrap v0.1.2 h1:v8xS0Z1LE7/6vMZA81PYihI+0TSR6Zm1MalzzBIuXKc=
|
github.com/sawka/txwrap v0.1.2 h1:v8xS0Z1LE7/6vMZA81PYihI+0TSR6Zm1MalzzBIuXKc=
|
||||||
github.com/sawka/txwrap v0.1.2/go.mod h1:T3nlw2gVpuolo6/XEetvBbk1oMXnY978YmBFy1UyHvw=
|
github.com/sawka/txwrap v0.1.2/go.mod h1:T3nlw2gVpuolo6/XEetvBbk1oMXnY978YmBFy1UyHvw=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/wavetermdev/ssh_config v0.0.0-20240109090616-36c8da3d7376/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg=
|
mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg=
|
||||||
mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8=
|
mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8=
|
||||||
|
@ -14,7 +14,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -25,6 +27,7 @@ import (
|
|||||||
"github.com/armon/circbuf"
|
"github.com/armon/circbuf"
|
||||||
"github.com/creack/pty"
|
"github.com/creack/pty"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/pkg/sftp"
|
||||||
"github.com/wavetermdev/waveterm/waveshell/pkg/base"
|
"github.com/wavetermdev/waveterm/waveshell/pkg/base"
|
||||||
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
||||||
"github.com/wavetermdev/waveterm/waveshell/pkg/server"
|
"github.com/wavetermdev/waveterm/waveshell/pkg/server"
|
||||||
@ -88,6 +91,9 @@ const WaveshellServerRunOnlyFmt = `
|
|||||||
[%PINGPACKET%]
|
[%PINGPACKET%]
|
||||||
mshell-[%VERSION%] --server
|
mshell-[%VERSION%] --server
|
||||||
`
|
`
|
||||||
|
const InitCommand = `
|
||||||
|
printf "\n##N{\"type\": \"init\", \"notfound\": true, \"uname\": \"%s|%s\"}\n" "$(uname -s)" "$(uname -m)";
|
||||||
|
`
|
||||||
|
|
||||||
func MakeLocalMShellCommandStr(isSudo bool) (string, error) {
|
func MakeLocalMShellCommandStr(isSudo bool) (string, error) {
|
||||||
mshellPath, err := scbase.LocalMShellBinaryPath()
|
mshellPath, err := scbase.LocalMShellBinaryPath()
|
||||||
@ -144,6 +150,7 @@ type pendingStateKey struct {
|
|||||||
// remove once ssh library is stabilized
|
// remove once ssh library is stabilized
|
||||||
type Launcher interface {
|
type Launcher interface {
|
||||||
Launch(*MShellProc, bool)
|
Launch(*MShellProc, bool)
|
||||||
|
RunInstall(*MShellProc)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MShellProc struct {
|
type MShellProc struct {
|
||||||
@ -175,6 +182,7 @@ type MShellProc struct {
|
|||||||
RunningCmds map[base.CommandKey]RunCmdType
|
RunningCmds map[base.CommandKey]RunCmdType
|
||||||
PendingStateCmds map[pendingStateKey]base.CommandKey // key=[remoteinstance name]
|
PendingStateCmds map[pendingStateKey]base.CommandKey // key=[remoteinstance name]
|
||||||
launcher Launcher // for conditional launch method based on ssh library in use. remove once ssh library is stabilized
|
launcher Launcher // for conditional launch method based on ssh library in use. remove once ssh library is stabilized
|
||||||
|
Client *ssh.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
type RunCmdType struct {
|
type RunCmdType struct {
|
||||||
@ -201,6 +209,10 @@ func (msh *MShellProc) Launch(interactive bool) {
|
|||||||
msh.launcher.Launch(msh, interactive)
|
msh.launcher.Launch(msh, interactive)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msh *MShellProc) RunInstall() {
|
||||||
|
msh.launcher.RunInstall(msh)
|
||||||
|
}
|
||||||
|
|
||||||
func (msh *MShellProc) GetStatus() string {
|
func (msh *MShellProc) GetStatus() string {
|
||||||
msh.Lock.Lock()
|
msh.Lock.Lock()
|
||||||
defer msh.Lock.Unlock()
|
defer msh.Lock.Unlock()
|
||||||
@ -1057,7 +1069,197 @@ func (msh *MShellProc) WaitAndSendPassword(pw string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msh *MShellProc) RunInstall() {
|
func (NewLauncher) RunInstall(msh *MShellProc) {
|
||||||
|
remoteCopy := msh.GetRemoteCopy()
|
||||||
|
if remoteCopy.Archived {
|
||||||
|
msh.WriteToPtyBuffer("*error: cannot install on archived remote\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
baseStatus := msh.GetStatus()
|
||||||
|
if baseStatus == StatusConnecting || baseStatus == StatusConnected {
|
||||||
|
msh.WriteToPtyBuffer("*error: cannot install on remote that is connected/connecting, disconnect to install\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
curStatus := msh.GetInstallStatus()
|
||||||
|
if curStatus == StatusConnecting {
|
||||||
|
msh.WriteToPtyBuffer("*error: cannot install on remote that is already trying to install, cancel current install to try again\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msh.WriteToPtyBuffer("installing mshell %s to %s...\n", scbase.MShellVersion, remoteCopy.RemoteCanonicalName)
|
||||||
|
clientCtx, clientCancelFn := context.WithCancel(context.Background())
|
||||||
|
defer clientCancelFn()
|
||||||
|
msh.WithLock(func() {
|
||||||
|
msh.InstallErr = nil
|
||||||
|
msh.InstallStatus = StatusConnecting
|
||||||
|
msh.InstallCancelFn = clientCancelFn
|
||||||
|
go msh.NotifyRemoteUpdate()
|
||||||
|
})
|
||||||
|
|
||||||
|
if msh.Remote.IsLocal() {
|
||||||
|
srcBinPath, err := scbase.MShellBinaryPath(base.MShellVersion, runtime.GOOS, runtime.GOARCH)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("ssh cannot create session: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
homeDir, err := os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("ssh cannot create session: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newBinName := fmt.Sprintf("mshell-%s", semver.MajorMinor(scbase.MShellVersion))
|
||||||
|
dstBinPath := filepath.Join(homeDir, ".mshell", newBinName)
|
||||||
|
|
||||||
|
srcBinFile, err := os.Open(srcBinPath)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("ssh cannot create session: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer srcBinFile.Close()
|
||||||
|
// destination file should be handled manually - not closed with defer
|
||||||
|
dstBinFile, err := os.OpenFile(dstBinPath, os.O_RDWR|os.O_CREATE, 0755)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("ssh cannot create session: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = io.Copy(dstBinFile, srcBinFile)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("ssh cannot create session: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
dstBinFile.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = dstBinFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("ssh cannot create session: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
session, err := msh.Client.NewSession()
|
||||||
|
defer session.Close()
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("ssh cannot create session: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cproc, initPk, err := shexec.MakeInstallProc(clientCtx, shexec.SessionWrap{Session: session, StartCmd: InitCommand}) //TODO
|
||||||
|
if err == context.Canceled {
|
||||||
|
msh.WriteToPtyBuffer("*install canceled\n")
|
||||||
|
msh.WithLock(func() {
|
||||||
|
msh.InstallStatus = StatusDisconnected
|
||||||
|
go msh.NotifyRemoteUpdate()
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("cannot create init packet: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer cproc.Close()
|
||||||
|
goos, goarch, err := shexec.DetectGoArch(initPk.UName)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("cannot determine architecture: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
srcBinPath, err := scbase.MShellBinaryPath(base.MShellVersion, goos, goarch)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("cannot find source binary: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileClient, err := sftp.NewClient(msh.Client)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("cannot estabish sftp connection: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
homeDir, err := fileClient.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("cannot determine remote home directory: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newBinName := fmt.Sprintf("mshell-%s", semver.MajorMinor(scbase.MShellVersion))
|
||||||
|
dstBinPath := filepath.Join(homeDir, ".mshell", newBinName)
|
||||||
|
|
||||||
|
srcBinFile, err := os.Open(srcBinPath)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("cannot find source executable: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer srcBinFile.Close()
|
||||||
|
// destination file should be handled manually - not closed with defer
|
||||||
|
dstBinFile, err := fileClient.OpenFile(dstBinPath, os.O_RDWR|os.O_CREATE)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("cannot create destination executable: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = dstBinFile.Chmod(0755)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("cannot set executable permissions: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = io.Copy(dstBinFile, srcBinFile)
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("unable to copy to new waveshell executable: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
dstBinFile.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = dstBinFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
statusErr := fmt.Errorf("unable to save waveshell executable: %w", err)
|
||||||
|
msh.WriteToPtyBuffer("*error, %s\n", statusErr.Error())
|
||||||
|
msh.setInstallErrorStatus(statusErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var connectMode string
|
||||||
|
msh.WithLock(func() {
|
||||||
|
msh.InstallStatus = StatusDisconnected
|
||||||
|
msh.InstallCancelFn = nil
|
||||||
|
msh.NeedsMShellUpgrade = false
|
||||||
|
msh.Status = StatusDisconnected
|
||||||
|
msh.Err = nil
|
||||||
|
connectMode = msh.Remote.ConnectMode
|
||||||
|
})
|
||||||
|
msh.WriteToPtyBuffer("successfully installed mshell %s to ~/.mshell\n", scbase.MShellVersion)
|
||||||
|
go msh.NotifyRemoteUpdate()
|
||||||
|
if connectMode == sstore.ConnectModeStartup || connectMode == sstore.ConnectModeAuto {
|
||||||
|
// the install was successful, and we don't have a manual connect mode, try to connect
|
||||||
|
go msh.Launch(true)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (LegacyLauncher) RunInstall(msh *MShellProc) {
|
||||||
remoteCopy := msh.GetRemoteCopy()
|
remoteCopy := msh.GetRemoteCopy()
|
||||||
if remoteCopy.Archived {
|
if remoteCopy.Archived {
|
||||||
msh.WriteToPtyBuffer("*error: cannot install on archived remote\n")
|
msh.WriteToPtyBuffer("*error: cannot install on archived remote\n")
|
||||||
@ -1381,6 +1583,7 @@ func (NewLauncher) Launch(msh *MShellProc, interactive bool) {
|
|||||||
msh.setErrorStatus(statusErr)
|
msh.setErrorStatus(statusErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
msh.Client = client
|
||||||
var session *ssh.Session
|
var session *ssh.Session
|
||||||
session, err = client.NewSession()
|
session, err = client.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user