aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2023-10-22 01:06:38 +0700
committerShulhan <ms@kilabit.info>2023-10-22 01:32:42 +0700
commitfc7cd444e7d637c291a3f9ba9987ba0335af4809 (patch)
treef1a32b5081417a1d64fe2cf88345ecf4494d3f97
parent4411ca1953c95ddc013e47c55e87303b7290e2cc (diff)
downloadawwan-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.go62
-rw-r--r--awwan_play_test.go44
-rw-r--r--session.go2
-rw-r--r--statement.go14
-rw-r--r--statement_test.go8
-rw-r--r--testdata/local/local.aww6
-rw-r--r--testdata/local/local_test.data13
-rw-r--r--testdata/play/awwanssh.test/play.aww5
-rw-r--r--testdata/play/awwanssh.test/play_test.data13
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`
diff --git a/session.go b/session.go
index 90c951d..6df9215 100644
--- a/session.go
+++ b/session.go
@@ -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