diff options
| author | Shulhan <ms@kilabit.info> | 2023-10-22 01:06:38 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2023-10-22 01:32:42 +0700 |
| commit | fc7cd444e7d637c291a3f9ba9987ba0335af4809 (patch) | |
| tree | f1a32b5081417a1d64fe2cf88345ecf4494d3f97 | |
| parent | 4411ca1953c95ddc013e47c55e87303b7290e2cc (diff) | |
| download | awwan-fc7cd444e7d637c291a3f9ba9987ba0335af4809.tar.xz | |
all: add magic command "#local"
The magic command "#local" define the command to be executed using
shell in local environment.
Its have effect and can only be used in script that executed using
"play".
In script that is executed using "local" it does nothing.
| -rw-r--r-- | awwan_local_test.go | 62 | ||||
| -rw-r--r-- | awwan_play_test.go | 44 | ||||
| -rw-r--r-- | session.go | 2 | ||||
| -rw-r--r-- | statement.go | 14 | ||||
| -rw-r--r-- | statement_test.go | 8 | ||||
| -rw-r--r-- | testdata/local/local.aww | 6 | ||||
| -rw-r--r-- | testdata/local/local_test.data | 13 | ||||
| -rw-r--r-- | testdata/play/awwanssh.test/play.aww | 5 | ||||
| -rw-r--r-- | testdata/play/awwanssh.test/play_test.data | 13 |
9 files changed, 167 insertions, 0 deletions
diff --git a/awwan_local_test.go b/awwan_local_test.go new file mode 100644 index 0000000..47195de --- /dev/null +++ b/awwan_local_test.go @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2023 M. Shulhan <ms@kilabit.info> +// SPDX-License-Identifier: GPL-3.0-or-later + +//go:build !integration + +package awwan + +import ( + "bytes" + "path/filepath" + "testing" + + "github.com/shuLhan/share/lib/test" + "github.com/shuLhan/share/lib/test/mock" +) + +func TestAwwanLocal(t *testing.T) { + var ( + baseDir = `testdata/local` + scriptDir = baseDir + scriptFile = filepath.Join(scriptDir, `local.aww`) + tdataFile = filepath.Join(scriptDir, `local_test.data`) + mockrw = mock.ReadWriter{} + + tdata *test.Data + aww *Awwan + err error + ) + + tdata, err = test.LoadData(tdataFile) + if err != nil { + t.Fatal(err) + } + + aww, err = New(baseDir) + if err != nil { + t.Fatal(err) + } + + // Mock terminal to read passphrase for private key. + aww.cryptoc.termrw = &mockrw + + var ( + req = NewRequest(CommandModeLocal, scriptFile, `1-`) + mockout = bytes.Buffer{} + mockerr = bytes.Buffer{} + ) + + req.stdout = &mockout + req.stderr = &mockerr + + err = aww.Local(req) + if err != nil { + t.Fatal(err) + } + + var exp = string(tdata.Output[`local:stdout`]) + test.Assert(t, `stdout`, exp, mockout.String()) + + exp = string(tdata.Output[`local:stderr`]) + test.Assert(t, `stderr`, exp, mockerr.String()) +} diff --git a/awwan_play_test.go b/awwan_play_test.go index 0894c3e..3026472 100644 --- a/awwan_play_test.go +++ b/awwan_play_test.go @@ -6,6 +6,7 @@ package awwan import ( + "bytes" "io/fs" "os" "path/filepath" @@ -27,6 +28,49 @@ type testCaseGetPut struct { expMode fs.FileMode } +func TestAwwan_Play_withLocal(t *testing.T) { + var ( + baseDir = `testdata/play` + scriptDir = filepath.Join(baseDir, `awwanssh.test`) + scriptFile = filepath.Join(scriptDir, `play.aww`) + tdataFile = filepath.Join(scriptDir, `play_test.data`) + + tdata *test.Data + aww *Awwan + err error + ) + + tdata, err = test.LoadData(tdataFile) + if err != nil { + t.Fatal(err) + } + + aww, err = New(baseDir) + if err != nil { + t.Fatal(err) + } + + var ( + req = NewRequest(CommandModePlay, scriptFile, `1-`) + mockout = bytes.Buffer{} + mockerr = bytes.Buffer{} + ) + + req.stdout = &mockout + req.stderr = &mockerr + + err = aww.Play(req) + if err != nil { + t.Fatal(err) + } + + var exp = string(tdata.Output[`play_with_local:stdout`]) + test.Assert(t, `stdout`, exp, mockout.String()) + + exp = string(tdata.Output[`play_with_local:stderr`]) + test.Assert(t, `stderr`, exp, mockerr.String()) +} + func TestAwwan_Play_Get(t *testing.T) { var ( baseDir = `testdata/play` @@ -504,6 +504,8 @@ func (ses *Session) executeScriptOnRemote(req *Request, pos linePosition) (err e err = ses.sshc.conn.Execute(string(stmt.raw)) case statementKindGet: err = ses.Get(stmt) + case statementKindLocal: + err = ExecLocal(req, stmt) case statementKindPut: err = ses.Put(stmt) case statementKindSudoGet: diff --git a/statement.go b/statement.go index ff59ca7..0468123 100644 --- a/statement.go +++ b/statement.go @@ -17,6 +17,7 @@ import ( const ( statementKindDefault int = iota statementKindComment + statementKindLocal statementKindRequire statementKindGet statementKindPut @@ -27,6 +28,7 @@ const ( // List of magic command. var ( cmdMagicGet = []byte(`#get:`) + cmdMagicLocal = []byte(`#local:`) cmdMagicPut = []byte(`#put:`) cmdMagicSudoGet = []byte(`#get!`) cmdMagicSudoPut = []byte(`#put!`) @@ -85,6 +87,18 @@ func ParseStatement(raw []byte) (stmt *Statement, err error) { args []string ) + if bytes.HasPrefix(raw, cmdMagicLocal) { + raw = raw[len(cmdMagicLocal):] + cmd, args = libexec.ParseCommandArgs(string(raw)) + stmt = &Statement{ + kind: statementKindLocal, + cmd: cmd, + args: args, + raw: raw, + } + return stmt, nil + } + if bytes.HasPrefix(raw, cmdMagicRequire) { raw = raw[len(cmdMagicRequire):] cmd, args = libexec.ParseCommandArgs(string(raw)) diff --git a/statement_test.go b/statement_test.go index 6da8dfe..009a658 100644 --- a/statement_test.go +++ b/statement_test.go @@ -137,6 +137,14 @@ func TestParseStatement(t *testing.T) { kind: statementKindComment, raw: []byte(`#requ: a`), }, + }, { + raw: []byte(`#local: echo "a"`), + exp: &Statement{ + kind: statementKindLocal, + cmd: `echo`, + args: []string{`a`}, + raw: []byte(` echo "a"`), + }, }} var ( diff --git a/testdata/local/local.aww b/testdata/local/local.aww new file mode 100644 index 0000000..3ee69f4 --- /dev/null +++ b/testdata/local/local.aww @@ -0,0 +1,6 @@ +echo "hello" + +## Should do nothing. +#local: echo "nothing" + +echo "local" diff --git a/testdata/local/local_test.data b/testdata/local/local_test.data new file mode 100644 index 0000000..1901f11 --- /dev/null +++ b/testdata/local/local_test.data @@ -0,0 +1,13 @@ +Test on "local" command. + +<<< local:stdout + +--> local: 1: echo "hello" +hello + +--> local: 4: #local: echo "nothing" + +--> local: 6: echo "local" +local + +<<< local:stderr diff --git a/testdata/play/awwanssh.test/play.aww b/testdata/play/awwanssh.test/play.aww new file mode 100644 index 0000000..c0f13ad --- /dev/null +++ b/testdata/play/awwanssh.test/play.aww @@ -0,0 +1,5 @@ +## Should print working directory on remote server. +pwd + +## Should print working directory on local. +#local: pwd diff --git a/testdata/play/awwanssh.test/play_test.data b/testdata/play/awwanssh.test/play_test.data new file mode 100644 index 0000000..764122b --- /dev/null +++ b/testdata/play/awwanssh.test/play_test.data @@ -0,0 +1,13 @@ +Test on "play" command. + +<<< play_with_local:stdout +--- SSH connection: awwanssh@127.0.0.1:10022 +--- SSH identity file: [/home/awwan/.ssh/id_ed25519] + +--> awwanssh@127.0.0.1:10022: 2: pwd +/home/awwanssh + +--> awwanssh@127.0.0.1:10022: 5: #local: pwd +/home/awwan/src + +<<< play_with_local:stderr |
