Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: surface plugin error in exec.go #1228

Merged
merged 6 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions pkg/common/plugin/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package plugin
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"os/exec"
Expand Down Expand Up @@ -46,6 +45,7 @@ type DefaultExecutor struct {
Stderr io.Writer
}

// return the command output and the error
func (e *DefaultExecutor) ExecutePlugin(ctx context.Context, pluginPath string, cmdArgs []string, stdinData []byte, environ []string) ([]byte, error) {
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
Expand Down Expand Up @@ -83,6 +83,7 @@ func (e *DefaultExecutor) ExecutePlugin(ctx context.Context, pluginPath string,
// If the plugin is about to be completed, then we wait a
// second and try it again
if strings.Contains(err.Error(), "text file busy") {
logrus.Debugf("command returned text file busy, retrying after %v", waitDuration)
time.Sleep(waitDuration)
continue
}
Expand All @@ -102,17 +103,16 @@ func (e *DefaultExecutor) ExecutePlugin(ctx context.Context, pluginPath string,
}

func (e *DefaultExecutor) pluginErr(err error, stdout, stderr []byte) error {
errMsg := Error{}
if len(stdout) == 0 {
if len(stderr) == 0 {
errMsg.Msg = fmt.Sprintf("plugin failed with no proper error message: %v", err)
} else {
errMsg.Msg = fmt.Sprintf("plugin failed with error: %q", string(stderr))
}
} else if perr := json.Unmarshal(stdout, &errMsg); perr != nil {
errMsg.Msg = fmt.Sprintf("plugin failed and parsing its error message also failed with error %q: %v", string(stdout), perr)
}
return &errMsg
var stdOutBuffer bytes.Buffer
var stdErrBuffer bytes.Buffer

// writing them to buffer to avoid lint error
stdOutBuffer.Write(stdout)
stdErrBuffer.Write(stderr)
binbin-li marked this conversation as resolved.
Show resolved Hide resolved

errCombined := Error{}
errCombined.Msg = fmt.Sprintf("plugin failed with error: '%v', msg from stError '%v', msg from stdOut '%v'", err.Error(), stdErrBuffer.String(), stdOutBuffer.String())
return &errCombined
}

func (e *DefaultExecutor) FindInPaths(plugin string, paths []string) (string, error) {
Expand Down
47 changes: 47 additions & 0 deletions pkg/common/plugin/exec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
Copyright The Ratify Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package plugin

import (
"strings"
"testing"
)

func TestPluginErr(t *testing.T) {
stdOut := []byte("This is a string from std out")
stdErr := []byte("This is a string from std err")
errMsg := Error{}
errMsg.Msg = "plugin error"

e := DefaultExecutor{}
err := e.pluginErr(&errMsg, stdOut, stdErr)
if err == nil {
t.Fatalf("plugin error expected")
}

if !strings.Contains(err.Error(), errMsg.Msg) {
t.Fatalf("error msg should contain stdOut error msg, actual '%v'", err.Error())
}

if !strings.Contains(err.Error(), string(stdOut)) {
t.Fatalf("error msg should contain stdOut msg, actual '%v'", err.Error())
}

if !strings.Contains(err.Error(), string(stdErr)) {
t.Fatalf("error msg should contain stdErr msg, actual '%v'", err.Error())
}
// check error contains the plugin error message
binbin-li marked this conversation as resolved.
Show resolved Hide resolved
}
Loading