Skip to content

Commit 903a6ef

Browse files
authored
Merge pull request #13 from rinocs/feat/new-exec-command
feat: add ExecCommand method for executing shell commands
2 parents 798478d + 0b556e2 commit 903a6ef

File tree

3 files changed

+141
-1
lines changed

3 files changed

+141
-1
lines changed

plugins/util.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package plugins
22

33
import (
4-
"github.com/Matrix86/driplane/utils"
4+
"errors"
55
"os"
6+
"os/exec"
7+
"strings"
68
"time"
9+
10+
"github.com/Matrix86/driplane/utils"
711
)
812

913
// UtilPackage contains useful generic methods
@@ -106,3 +110,41 @@ func (c *UtilPackage) Sha512File(filename string) UtilResponse {
106110
Value: hash,
107111
}
108112
}
113+
114+
// Ecexute shell command
115+
func (c *UtilPackage) ExecCommand(commandParts []string, inputData string) UtilResponse {
116+
if len(commandParts) == 0 {
117+
return UtilResponse{
118+
Error: errors.New("no command provided"),
119+
Status: false,
120+
Value: "",
121+
}
122+
}
123+
124+
executable := commandParts[0]
125+
args := commandParts[1:]
126+
127+
cmd := exec.Command(executable, args...)
128+
129+
// If inputData is provided, write it to the command's Stdin
130+
// This replaces '<<EOF'
131+
if inputData != "" {
132+
cmd.Stdin = strings.NewReader(inputData)
133+
}
134+
135+
output, err := cmd.CombinedOutput()
136+
137+
if err != nil {
138+
return UtilResponse{
139+
Error: err,
140+
Status: false,
141+
Value: string(output),
142+
}
143+
}
144+
145+
return UtilResponse{
146+
Error: nil,
147+
Status: true,
148+
Value: string(output),
149+
}
150+
}

plugins/util_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package plugins
22

33
import (
44
"os"
5+
"runtime"
6+
"strings"
57
"testing"
68
)
79

@@ -129,3 +131,76 @@ func TestUtilPluginSha512Method(t *testing.T) {
129131
t.Errorf("Value has a bad value: expected=%s had=%s", expected, res.Value)
130132
}
131133
}
134+
135+
func TestUtilPluginExecCommandMethod(t *testing.T) {
136+
u := GetUtil()
137+
138+
var echoCmd []string
139+
expectedOutput := "hello world"
140+
if runtime.GOOS == "windows" {
141+
echoCmd = []string{"cmd", "/C", "echo", expectedOutput}
142+
} else {
143+
echoCmd = []string{"echo", expectedOutput}
144+
}
145+
146+
tests := []struct {
147+
name string // test name
148+
cmdParts []string // command
149+
inputData string // stdin
150+
expectedStatus bool // status field of the response
151+
expectError bool // Error field of the response
152+
expectedValue string // returned value of the command
153+
}{
154+
{
155+
name: "Error: no command ",
156+
cmdParts: []string{},
157+
inputData: "",
158+
expectedStatus: false,
159+
expectError: true,
160+
expectedValue: "",
161+
},
162+
{
163+
name: "Success: Simple Echo command",
164+
cmdParts: echoCmd,
165+
inputData: "",
166+
expectedStatus: true,
167+
expectError: false,
168+
expectedValue: expectedOutput,
169+
},
170+
{
171+
name: "Error: Command not exist",
172+
cmdParts: []string{"not_existing_command_12345"},
173+
inputData: "",
174+
expectedStatus: false,
175+
expectError: true,
176+
expectedValue: "",
177+
},
178+
}
179+
180+
for _, tt := range tests {
181+
t.Run(tt.name, func(t *testing.T) {
182+
response := u.ExecCommand(tt.cmdParts, tt.inputData)
183+
184+
if response.Status != tt.expectedStatus {
185+
t.Errorf("Wrong status: expected %v, obtained %v", tt.expectedStatus, response.Status)
186+
}
187+
188+
if tt.expectError && response.Error == nil {
189+
t.Errorf("Expected error but obtained nil")
190+
}
191+
if !tt.expectError && response.Error != nil {
192+
t.Errorf("Error not expected but obtained: %v", response.Error)
193+
}
194+
195+
cleanOutput := strings.TrimSpace(response.Value)
196+
197+
if tt.expectedValue != "" {
198+
199+
if !strings.Contains(cleanOutput, tt.expectedValue) {
200+
t.Errorf("Wrong output. \n Expected: %q\n Obtained: %q", tt.expectedValue, cleanOutput)
201+
}
202+
}
203+
})
204+
}
205+
206+
}

src_docs/content/doc/filters/js/packages.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,26 @@ The return value will be a JS object containing the following fields:
143143
|------------------------------------------------|---------------------------------------------------------------------------------------------|
144144
| cache.Put(key string, value string, ttl int64) | add the `value` in the cache using the key `key` and it will be deleted after `ttl` seconds |
145145
| cache.Get(key string) | get the value stored in the cache with the key `key` |
146+
147+
148+
### Exec COmmand
149+
150+
This package contains functions for executing system commands and handling system interactions.
151+
152+
#### Return
153+
154+
The return value will be a JS object containing the following fields:
155+
156+
| Name | Type | Description |
157+
|--------|----------|----------------------------------------------------------|
158+
| Status | _BOOL_ | if true the operation was successful |
159+
| Error | _STRING_ | if status is false it contains the reason of the failure |
160+
| Value | _STRING_ | if status is true it contains the standard output |
161+
162+
#### Functions
163+
164+
| Prototype | Description |
165+
|-----------------------------------------------------------|----------------------------------------------------------------------------------------------|
166+
| util.ExecCommand(commandParts []string, inputData string) | Executes the system command defined in `commandParts`. <br> - `commandParts[0]` is the |
167+
| | executable. <br> - `commandParts[1:]` are the arguments. <br> - inputData` is written to the|
168+
| | Standard Input (stdin) of the command. |

0 commit comments

Comments
 (0)