Skip to content

Commit

Permalink
Merge pull request #190 from ThinkMo/main
Browse files Browse the repository at this point in the history
Adds support for append feature to function  capture_local
  • Loading branch information
vladimirvivien authored Jan 15, 2021
2 parents 3e9c3f5 + de2dc98 commit e174dd1
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 12 deletions.
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ This function runs a command locally on the machine running the script. It then
| `workdir`|A parent directory where captured files will be saved|No, defaults to `crashd_config.workdir`|
| `file_name`|The path/name of the generated file|No, auto-generated based on command string, if omitted|
| `desc`|A short description added at the start of the file|No|
| `append` | boolean indicator to append to a file if it already exists or not |No, defaults to `False`|

#### Output
`capture_local()` returns the full path of the capured output file.
Expand Down Expand Up @@ -767,4 +768,4 @@ bloop blah
# this will result in a warning message with foo=bar as the only pair pairs to be passed to the .crsh file
$ crash run diagnsotics.crsh --args-file /tmp/script.args
WARN[0000] unknown entry in args file: blooop blah
```
```
15 changes: 11 additions & 4 deletions starlark/capture.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,26 +163,33 @@ func execCaptureSSH(host, cmdStr, rootDir, fileName, desc string, agent ssh.Agen
reader, err := ssh.RunRead(args, agent, cmdStr)
if err != nil {
logrus.Errorf("%s failed: %s", identifiers.capture, err)
if err := captureOutput(strings.NewReader(err.Error()), filePath, fmt.Sprintf("%s: failed", cmdStr)); err != nil {
if err := captureOutput(strings.NewReader(err.Error()), filePath, fmt.Sprintf("%s: failed", cmdStr), false); err != nil {
logrus.Errorf("%s output failed: %s", identifiers.capture, err)
return commandResult{resource: args.Host, result: filePath, err: err}, err
}
}

if err := captureOutput(reader, filePath, desc); err != nil {
if err := captureOutput(reader, filePath, desc, false); err != nil {
logrus.Errorf("%s output failed: %s", identifiers.capture, err)
return commandResult{resource: args.Host, result: filePath, err: err}, err
}

return commandResult{resource: args.Host, result: filePath, err: err}, nil
}

func captureOutput(source io.Reader, filePath, desc string) error {
func captureOutput(source io.Reader, filePath, desc string, append bool) error {
if source == nil {
return fmt.Errorf("source reader is nill")
}

file, err := os.Create(filePath)
flag := os.O_CREATE | os.O_WRONLY
if append {
flag |= os.O_APPEND
} else {
flag |= os.O_TRUNC
}

file, err := os.OpenFile(filePath, flag, 0644)
if err != nil {
return err
}
Expand Down
6 changes: 4 additions & 2 deletions starlark/capture_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ import (

// 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])
// Starlark format: run_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
if err := starlark.UnpackArgs(
identifiers.captureLocal, args, kwargs,
"cmd", &cmdStr,
"workdir?", &workdir,
"file_name?", &fileName,
"desc?", &desc,
"append?", &append,
); err != nil {
return starlark.None, fmt.Errorf("%s: %s", identifiers.captureLocal, err)
}
Expand All @@ -48,7 +50,7 @@ func captureLocalFunc(thread *starlark.Thread, b *starlark.Builtin, args starlar
return starlark.None, fmt.Errorf("%s: %s", identifiers.captureLocal, p.Err())
}

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

Expand Down
39 changes: 34 additions & 5 deletions starlark/capture_local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,29 @@ func TestCaptureLocalFunc(t *testing.T) {
{starlark.String("workdir"), starlark.String("/tmp/capturecrashd")},
{starlark.String("file_name"), starlark.String("echo.txt")},
{starlark.String("desc"), starlark.String("echo command")},
{starlark.String("append"), starlark.True},
}
},
eval: func(t *testing.T, kwargs []starlark.Tuple) {
expected := filepath.Join("/tmp/capturecrashd", "echo.txt")
err := os.MkdirAll("/tmp/capturecrashd", 0777)
if err != nil {
t.Fatal(err)
}
f, err := os.OpenFile(expected, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
if _, err := f.Write([]byte("Hello World!\n")); err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}
val, err := captureLocalFunc(newTestThreadLocal(t), nil, nil, kwargs)
if err != nil {
t.Fatal(err)
}
expected := filepath.Join("/tmp/capturecrashd", "echo.txt")
result := ""
if r, ok := val.(starlark.String); ok {
result = string(r)
Expand All @@ -100,7 +115,7 @@ func TestCaptureLocalFunc(t *testing.T) {
t.Fatal(err)
}
expected = strings.TrimSpace(buf.String())
if expected != "echo command\nHello World!" {
if expected != "Hello World!\necho command\nHello World!" {
t.Errorf("unexpected content captured: %s", expected)
}
if err := file.Close(); err != nil {
Expand Down Expand Up @@ -174,15 +189,29 @@ result = capture_local("echo 'Hello World!'")
{
name: "capture local with args",
script: `
result = capture_local(cmd="echo 'Hello World!'", workdir="/tmp/capturecrash", file_name="echo_out.txt", desc="output command")
result = capture_local(cmd="echo 'Hello World!'", workdir="/tmp/capturecrash", file_name="echo_out.txt", desc="output command", append=True)
`,
eval: func(t *testing.T, script string) {
expected := filepath.Join("/tmp/capturecrash", "echo_out.txt")
err := os.MkdirAll("/tmp/capturecrash", 0777)
if err != nil {
t.Fatal(err)
}
f, err := os.OpenFile(expected, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
if _, err := f.Write([]byte("Hello World!\n")); err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}
exe := New()
if err := exe.Exec("test.star", strings.NewReader(script)); err != nil {
t.Fatal(err)
}

expected := filepath.Join("/tmp/capturecrash", "echo_out.txt")
var result string
resultVal := exe.result["result"]
if resultVal == nil {
Expand Down Expand Up @@ -211,7 +240,7 @@ result = capture_local(cmd="echo 'Hello World!'", workdir="/tmp/capturecrash", f
t.Fatal(err)
}
expected = strings.TrimSpace(buf.String())
if expected != "output command\nHello World!" {
if expected != "Hello World!\noutput command\nHello World!" {
t.Errorf("unexpected content captured: %s", expected)
}
if err := file.Close(); err != nil {
Expand Down

0 comments on commit e174dd1

Please sign in to comment.