Skip to content

Commit

Permalink
Script command capture_local does not stop execution
Browse files Browse the repository at this point in the history
This patch modifies script command capture_local to avoid crashing
the script execution upon error. This fix captures the command error
and writes it in the file and contines the script execution.

Signed-off-by: Vladimir Vivien <[email protected]>
  • Loading branch information
vladimirvivien committed Oct 3, 2021
1 parent 8833fa2 commit 32b93ae
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 7 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.7.0
github.com/spf13/cobra v1.1.1
github.com/vladimirvivien/gexe v0.1.0
github.com/vladimirvivien/gexe v0.1.1
go.starlark.net v0.0.0-20201006213952-227f4aabceb5
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,8 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/vladimirvivien/gexe v0.1.0 h1:Dge3QyscrV/yhmZkWDO6SXhrpyz+C6HnH8e+LVjhUus=
github.com/vladimirvivien/gexe v0.1.0/go.mod h1:LHQL00w/7gDUKIak24n801ABp8C+ni6eBht9vGVst8w=
github.com/vladimirvivien/gexe v0.1.1 h1:2A0SBaOSKH+cwLVdt6H+KkHZotZWRNLlWygANGw5DxE=
github.com/vladimirvivien/gexe v0.1.1/go.mod h1:LHQL00w/7gDUKIak24n801ABp8C+ni6eBht9vGVst8w=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
17 changes: 13 additions & 4 deletions starlark/capture_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/vladimirvivien/gexe"
"go.starlark.net/starlark"
)

// captureLocalFunc is a built-in starlark function that runs a provided command on the local machine.
// The output of the command is stored in a file at a specified location under the workdir directory.
// Starlark format: run_local(cmd=<command> [,workdir=path][,file_name=name][,desc=description][,append=append])
// Starlark format: capture_local(cmd=<command> [,workdir=path][,file_name=name][,desc=description][,append=append])
func captureLocalFunc(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
var cmdStr, workdir, fileName, desc string
var append bool
Expand Down Expand Up @@ -42,16 +43,24 @@ func captureLocalFunc(thread *starlark.Thread, b *starlark.Builtin, args starlar

filePath := filepath.Join(workdir, fileName)
if err := os.MkdirAll(workdir, 0744); err != nil && !os.IsExist(err) {
return starlark.None, fmt.Errorf("%s: %s", identifiers.captureLocal, err)
msg := fmt.Sprintf("%s error: %s", identifiers.captureLocal, err)
return starlark.String(msg), nil
}

p := gexe.StartProc(cmdStr)
// upon error, write error in file, return filepath
if p.Err() != nil {
return starlark.None, fmt.Errorf("%s: %s", identifiers.captureLocal, p.Err())
msg := fmt.Sprintf("%s error: %s: %s", identifiers.captureLocal, p.Err(), p.Result())
if err := captureOutput(strings.NewReader(msg), filePath, desc, append); err != nil {
msg := fmt.Sprintf("%s error: %s", identifiers.captureLocal, err)
return starlark.String(msg), nil
}
return starlark.String(filePath), nil
}

if err := captureOutput(p.Out(), filePath, desc, append); err != nil {
return starlark.None, fmt.Errorf("%s: %s", identifiers.captureLocal, err)
msg := fmt.Sprintf("%s error: %s", identifiers.captureLocal, err)
return starlark.String(msg), nil
}

return starlark.String(filePath), nil
Expand Down
36 changes: 36 additions & 0 deletions starlark/capture_local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,42 @@ func TestCaptureLocalFunc(t *testing.T) {
}
},
},
{
name: "capture with error",
args: func(t *testing.T) []starlark.Tuple {
return []starlark.Tuple{{starlark.String("cmd"), starlark.String("nacho 'Hello World!'")}}
},
eval: func(t *testing.T, kwargs []starlark.Tuple) {
val, err := captureLocalFunc(newTestThreadLocal(t), nil, nil, kwargs)
if err != nil {
t.Fatal(err)
}
result := ""
if r, ok := val.(starlark.String); ok {
result = string(r)
}
defer func() {
os.RemoveAll(result)
os.RemoveAll(defaults.workdir)
}()

file, err := os.Open(result)
if err != nil {
t.Fatal(err)
}
buf := new(bytes.Buffer)
if _, err := io.Copy(buf, file); err != nil {
t.Fatal(err)
}
expected := strings.TrimSpace(buf.String())
if !strings.Contains(expected, "not found") {
t.Errorf("unexpected content captured: %s", expected)
}
if err := file.Close(); err != nil {
t.Error(err)
}
},
},
}

for _, test := range tests {
Expand Down

0 comments on commit 32b93ae

Please sign in to comment.